截获泛型类中的方法调用

本文关键字:方法 调用 泛型类 | 更新日期: 2023-09-27 17:58:59

我有这个代码:

abstract class CommunicationChannel<Client> : IDisposable where Client :  class, IDisposable {
    protected Client client;
    public void Open() {
        try
        {
            client = CreateClient();
        }
        catch (Exception)
        {
            client.Dispose();
            throw;
        }
    }
    public virtual void  Dispose() {
        client.Dispose();
    }
    private Client CreateClient()
    {
        return Activator.CreateInstance<Client>();
    }
}
class Communicator : CommunicationChannel<Client>
{
    // here I have specific methods
    void Method1(args) {
        Open();
        try {
            client.Method1(args);
        }
        catch(Exception) {
            // Cleanup
        }
    }
    // this is getting too verbose already
    void Method2(args) {
        Open();
        try {
            client.Method2(args);
        }
        catch(Exception) {
            // Cleanup
        }
    }
} 
class Client: IDisposable {
    public void Dispose()
    {
    }
}

我希望基类CommunicationChannel能够以某种方式截获所有与客户端相关的调用,并在将异常传播到派生类CommunicationChannel之前处理异常。基类的泛型参数可以包含不同的方法(在我的示例中,我们只有方法1)

理想情况下,我想要一个不必调用CommunicationChannel.CallMethod("Method1",args)的解决方案。

截获泛型类中的方法调用

您可以将client设为私有,并强制子类在FuncAction中访问它。然后您可以在逻辑之前/之后添加您:

abstract class CommunicationChannel<Client> : IDisposable where Client : class, IDisposable
{
    private Client client;
        protected TResult WithClient<TResult>(Func<Client, TResult> f)
        {
            this.Open();
            try
            {
                return f(client);
            }
            catch (Exception)
            {
                //cleanup
            }
            return default(TResult);
        }
    protected void WithClient(Action<Client> act)
    {
        WithClient<object>(c => { act(c); return null; })
    }
}

您的子类可以执行以下操作:

class Communicator : CommunicationChannel<Client> 
{
    bool Method1(args) 
    {
        return WithClient<bool>(c => { return c.Method1(args); });
    }
}

我认为这是使用AOP(面向方面编程)的一个很好的例子。

您可以设置一个方面,即OnEntry,执行Open方法并用OnException方法捕获异常。

然后你所要做的就是用属性装饰你想在上面使用该方面的方法

我将使用PostSharp:演示我的意思

public class CommunicationAspect : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        var communicationObject = args.Instance as CommunicationObject;
        communicationObject.Open();
        args.FlowBehavior = FlowBehavior.Continue;
    }
    public override void OnException(MethodExecutionArgs args)
    {
        _logger.log(string.Format("Exception {0} has occured on method {1}", args.Exception, args.Method.Name));
    }
}

然后,用这个属性装饰你的方法:

class Communicator : CommunicationChannel<Client>
{
  [CommunicationAspect]
  void Method1(args) 
  {
     client.Method1(args);
  }
  [CommunicationAspect]
  void Method2(args)
  {
     client.Method2(args);
  }
}

PostSharp是一个很好的框架,它非常容易上手,我建议你研究一下。