2011-09-06 46 views
0

有什麼辦法可以動態攔截在C#類的方法調用,相當於Perl的AUTOLOAD機制?在點有任何C#相當於Perl的AUTOLOAD?

案例,我有一個輔助類與寫入系統事件日誌和一些便利重載簡化最常見的用途「核心」的方法。

現在,我看到了,我用的try ... catch嘗試寫一個條目,但忽略那些與實際事件日誌處理任何故障新興代碼模式。例如試圖在事件日誌已滿登錄應用程序異常的時候,我希望應用程序與「真正的」應用程序異常崩潰,而不是「事件日誌」異常。

我目前剛剛創建了一組新的重載封裝了這個,但我真正想做的是對這些方法進行動態處理,即對以「Try」開頭的方法名稱的任何方法調用分別調用「真實」的方法,封裝在try ... catch中。這在Perl中會很容易;-)但它甚至可以在C#中完成嗎?

一些代碼,可能簡化解釋:

public class SomeClass 
{ 
    // Core functionality 
    public static void WriteToLog(string message, EventLogEntryType type) 
    { 
     ... 
    } 

    // Overloaded methods for common uses 
    public static void WriteToLog(SomeObject obj) 
    { 
     WriteToLog(obj.ToString(), EventLogEntryType.Information); 
    } 

    public static void WriteToLog(SomeException ex) 
    { 
     WriteToLog(ex.Message, EventLogEntryType.Error); 
    } 

    // Additional wrappers that ignores errors 
    // These are what I'd like to handle dynamically instead of manually: 
    public static void TryWriteToLog(SomeObject obj) 
    { 
     try 
     { 
      WriteToLog(obj); 
     } 
     catch (Exception logException) 
     { 
      Console.WriteLine(logException.Message); 
     } 
    } 

    public static void TryWriteToLog(SomeException ex) 
    { 
     try 
     { 
      WriteToLog(ex); 
     } 
     catch (Exception logException) 
     { 
      Console.WriteLine(logException.Message); 
     } 
    } 
} 
+0

可能重複的[如何截取C#中的方法調用?](http://stackoverflow.com/questions/25803/how-do-i-intercept-a-method-call-in-c) – Jamiec

+0

@Jamiec不完全是,因爲我有興趣重定向函數調用,而不僅僅是記錄它。 – Christoffer

+0

想通了我自己的答案,但我會留下開放的問題,現在的情況下,任何人來了一個更好的解決方案。 – Christoffer

回答

0

哦...... 出乎我的意料,我想通了超過一杯咖啡,它的實際工作。套用的初始代碼段,這裏就是我所做的:

using System; 
using System.Dynamic; 
using System.Reflection; 

public class SomeClass : DynamicObject 
{ 
    // Core functionality 
    public static void WriteToLog(string message, EventLogEntryType type) 
    { 
     ... 
    } 

    // Overloaded methods for common uses 
    public static void WriteToLog(SomeObject obj) 
    { 
     WriteToLog(obj.ToString(), EventLogEntryType.Information); 
    } 

    public static void WriteToLog(SomeException ex) 
    { 
     WriteToLog(ex.Message, EventLogEntryType.Error); 
    } 

    // Redirect all method calls that start with 'Try' to corresponding normal 
    // methods, but encapsulate the method call in a try ... catch to ignore 
    // log-related errors 

    private static dynamic instance = new SomeClass(); 

    public static dynamic Instance { get { return instance; } } 

    public override bool TryInvokeMember(InvokeMemberBinder binder, 
             object[] args, 
             out object result) 
    { 
     if (binder.Name.StartsWith("Try")) 
     { 
      try 
      { 
       result = this.GetType().InvokeMember(binder.Name.Substring(3), 
                BindingFlags.InvokeMethod, 
                null, 
                this, 
                args); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.InnerException.Message); 
       result = null; 
      } 
      return true; 
     } 
     else 
     { 
      return base.TryInvokeMember(binder, args, out result); 
     } 
    } 

下面的方法現在可以調用,並且似乎打算工作:

SomeClass.Instance.WriteToLog(SomeObject obj) 
SomeClass.Instance.TryWriteToLog(SomeObject obj) 
SomeClass.Instance.WriteToLog(SomeException ex) 
SomeClass.Instance.TryWriteToLog(SomeException ex) 
SomeClass.Instance.WriteToLog(string message, EventLogEntryType type) 
SomeClass.Instance.TryWriteToLog(string message, EventLogEntryType type) 

小告誡:上面的代碼被清理在官方論壇上發佈,它可能無法正常工作。