Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在泛型类中拦截方法调用_C#_Generics - Fatal编程技术网

C# 在泛型类中拦截方法调用

C# 在泛型类中拦截方法调用,c#,generics,C#,Generics,我有以下代码: abstract class CommunicationChannel<Client> : IDisposable where Client : class, IDisposable { protected Client client; public void Open() { try { client = CreateClient(); } catch (Ex

我有以下代码:

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()
    {

    }
}
抽象类通信通道:IDisposable其中客户端:class,IDisposable{
受保护的客户端;
公开作废{
尝试
{
client=CreateClient();
}
捕获(例外)
{
client.Dispose();
投掷;
}
}
公共虚拟void Dispose(){
client.Dispose();
}
私有客户端CreateClient()
{
返回Activator.CreateInstance();
}
}
类通讯器:通讯通道
{
//这里我有具体的方法
无效方法1(args){
Open();
试一试{
方法1(args);
}
捕获(例外){
//清理
}
}
//这已经太冗长了
无效方法2(args){
Open();
试一试{
方法2(args);
}
捕获(例外){
//清理
}
}
} 
类客户端:IDisposable{
公共空间处置()
{
}
}
我希望在基类CommunicationChannel中能够以某种方式截获与客户机相关的所有调用,并在将它们传播到派生类CommunicationChannel之前处理异常。基类的泛型参数可以包含不同的方法(在我的示例中,我们只有方法1)


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

您可以将
客户端
设为私有,并强制子类在
函数
操作
中访问它。然后,您可以在逻辑之前/之后添加:

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; })
    }
}
抽象类通信通道:IDisposable其中客户端:class,IDisposable
{
私人客户;
带客户端的受保护TResult(函数f)
{
这个.Open();
尝试
{
返回f(客户);
}
捕获(例外)
{
//清理
}
返回默认值(TResult);
}
受保护的客户无效(行动法案)
{
WithClient(c=>{act(c);返回null;})
}
}
然后,您的子类可以执行以下操作:

class Communicator : CommunicationChannel<Client> 
{
    bool Method1(args) 
    {
        return WithClient<bool>(c => { return c.Method1(args); });
    }
}
类通信器:通信通道
{
布尔方法1(args)
{
返回WithClient(c=>{return c.Method1(args);});
}
}

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

您所能做的是设置一个方面,该方面支持onetry,执行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);
  }
}
类通信器:通信通道
{
[通信方面]
无效方法1(args)
{
方法1(args);
}
[通信方面]
无效方法2(args)
{
方法2(args);
}
}

是一个非常好的框架,可以让您轻松入门,我建议您研究一下。

WithClient还必须处理不同的返回类型,例如c.MethodX return看起来更好的类型:-)。与客户通话时仍需要一个,返回值不扣除。。。是一个构建在JSON之上的库,它提供了一种快速、不引人注目的方式来为您的.NET应用程序编写方法拦截器。这是一个维基。你可以试试这个:)