簡體   English   中英

攔截方法調用泛型類

[英]Intercept method calls in a generic class

我有這個代碼:

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方法捕獲異常。

然后,您所要做的就是使用Attribute來裝飾要使用該方面的方法

我用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是一個很棒的框架,讓它很容易上手,我建議你研究一下。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM