2015-09-01 54 views
0

我試圖爲裝飾方法開發一個自定義屬性,當我這樣做時,我希望它們被屬性「捕獲」,以便它決定如何處理異常。C#AOP自定義屬性Unity

我所知道的專門兩種技術來做到這一點: - PostSharp - 企業庫統一

我想避免的第一個,我想已經與團結繼續下去,因爲我們使用企業庫。

因此,爲了使這項工作,我已經做了以下內容:

我調用句柄:

public class LoggingCallHandler : ICallHandler 
{ 
    public bool Rethrow 
    { 
     get; set; 
    } 

    public bool Log 
    { 
     get; set; 
    } 

    public int Order 
    { 
     get; set; 
    } 

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) 
    { 
     var result = getNext().Invoke(input, getNext); 

     if (result.Exception != null) 
     { 
      if (this.Rethrow) 
       throw result.Exception; 

      if (this.Log) 
       this.LogException(result.Exception); 
     } 

     return result; 
    } 

    private void LogException(Exception ex) 
    { 
     // Do stuff 
    } 
} 

我的自定義屬性

public class LoggingCallHandlerAttribute : HandlerAttribute 
{ 
    private bool rethrow; 

    private bool log; 

    public LoggingCallHandlerAttribute(bool rethrow, bool log = false) 
    { 
     this.rethrow = rethrow; 
     this.log = log; 
    } 

    public override ICallHandler CreateHandler(IUnityContainer container) 
    { 
     return new LoggingCallHandler() { Rethrow = this.rethrow, Log = this.log }; 
    } 
} 

我類的方法用屬性裝飾

public class TestManager 
{ 
    [LoggingCallHandler(false, false)] 
    public void DoStuff() 
    { 
     throw new Exception("TEST"); 
    } 
} 

當我運行該方法時,不會發生AOP。

我知道thar Unity可能依賴或依賴容器。但是我們目前不使用任何這種方法,所以我們只想用[LoggingCallHandler]屬性來修飾一個方法,就是這樣。

如果容器確實是必需的,那麼可以考慮它,但如果有一個適合所有用途的單個容器(至少現在是這樣)會很好。

有沒有可能做到這一點?

謝謝你們。

回答

0

如果你不使用Unity容器來構造你的對象,那麼攔截(通過ICallHandler)將不起作用。

當您通過Unity DI容器創建對象時,這種攔截依賴於Unity來包裝對象。

即使您不使用DI容器,PostSharp攔截也可以工作。

如果您不使用DI容器(IMO),那麼您可以更好地保持原樣,並且不要在代碼庫中引入DI容器。看到我的文章here

您可能還想考慮使用DynamicProxy進行截取。但是這需要您在創建對象時手動包裝對象。

1

我積極致力於NConcern .NET AOP Framework一個新的開源項目。你可以嘗試做你需要的。

看點來管理您的異常處理

public class ExceptionHandlingAspect : IAspect 
{ 
    private void Log(Exception exception) 
    { 
     //... 
    } 

    public IEnumerable<IAdvice> Advise(MethodInfo method) 
    { 
     //advise only if method is tagged. 
     if (Attribute.IsDefined(method, typeof(LoggingCallHandlerAttribute)) 
     { 
      //get attribute 
      var attribute = method.GetCustomAttributes(typeof(LoggingCallHandlerAttribue))[0] as LoggingCallHandlerAttribute; 

      //describe how yo rewrite method. 
      yield return Advice.Basic.Arround(invoke => 
      { 
       try { invoke(); } //call original code 
       catch (Exception e) 
       { 
        if (attribute.Rethrow) 
        { 
         throw; 
        } 

        if (attribute.Log) 
        { 
         this.Log(e); 
        } 
       } 
      }); 
     } 
    } 
} 

連接方面與LoggingCallHandlerAttribute歸屬的所有方法;

Aspect.Weave<ExceptionHandlingAspect>(method => method.IsDefined(typeof(LoggingCallHandlerAttribute), true);