2011-07-05 68 views
8

我們正在使用IoC,並將我們的日誌暴露出來。我們使用的是Common.Logging,我寫了一個Common.Logging.FormatMessageHandler的匹配代理,但我不知道如何將該代理的版本轉換爲Common.Logging api所期望的版本。從一個代表轉換爲另一個代表。僞鑄造

這個問題似乎是相似的,但我不明白如何從我的實施類型轉換爲我想調用的已知類型。 Dynamically casting one type of delegate to another

這裏是我的委託簽名:

public delegate string FormatMessageHandler(string format, params object[] args) 

這裏是Common.Logging的:

public delegate string FormatMessageHandler(string format, params object[] args) 

相同的名稱(不說是事務)以及相同數目的參數。兩者在編譯時都是已知的,所以它應該是顯而易見的,但我沒有看到它。

回答

7

爲什麼你不使用Common.Logging的委託,如果它是完全一樣的?
然而,孤子您的問題是,要麼使用動態轉換在你所提到的問題鏈接的文章中解釋,或者你不喜歡這樣寫道:

YourNamespace.FormatMessageHandler yourHandler = ...; 
Common.Logging.FormatMessageHandler handler = (f, a) => yourHandler(f, a); 

UPDATE:
根據您的發表評論,你想這樣的事情:

public void Error(Action<Your.FormatMessageHandler> formatMessageCallback) 
{ 
    _logger.Error(h => formatMessageCallback((f, a) => h(f, a))); 
} 

這將創建一個新的動作與一個參數Common.Logging.FormatMessageHandler類型的h這就要求所提供的行動formatMessageCallback與新代表Your.FormatMessageHandler接受兩個參數fa。這個新代表反過來調用h提供的兩個參數。

+0

你的解釋是偉大的工作,直到我試圖用行動。我如何處理Action? (Action formatMessageCallback) 我的方法簽名: public void Error –

+0

我不公開Common.Logging委託或任何API,因爲我們決定在將來使用不同的日誌記錄框架。如果發生這種情況,那麼我們所要做的就是編寫一些代碼,這些代碼實現了我們之前定義的日誌接口,並將這些調用包裝到新的日誌框架中。 –

+0

@大衛:沒有使用記錄器的委託的原因是有效的,謝謝解釋。請參閱更新以獲取您的第一條評論的解決方案。 –

1

手動您可以做到這一點,但它與轉換過程中涉及的反射一樣昂貴。一旦委託轉換它的行爲基本上是相同的......

internal class Program 
{ 
    //An example delegate target 
    static void Click(object o, EventArgs e) { } 

    //A simple test method 
    static void Main(string[] args) 
    { 
     EventHandler onclick = Click; 
     EventHandler<EventArgs> converted; 
     if (!TryConvertDelegate(onclick, out converted)) 
      throw new Exception("failed"); 
    } 

    //The conversion of one delegate type to another 
    static bool TryConvertDelegate<TOldType, TNewType>(TOldType oldDelegate, out TNewType newDelegate) 
     where TOldType : class, System.ICloneable, System.Runtime.Serialization.ISerializable 
     where TNewType : class, System.ICloneable, System.Runtime.Serialization.ISerializable 
    { 
     if (!typeof(Delegate).IsAssignableFrom(typeof(TOldType)) || !typeof(Delegate).IsAssignableFrom(typeof(TNewType))) 
      throw new ArgumentException(); //one of the types is not a delegate 

     newDelegate = default(TNewType); 
     Delegate handler = oldDelegate as System.Delegate; 
     if (handler == null) 
      return true; //null in, null out 

     Delegate result = null; 
     foreach (Delegate d in handler.GetInvocationList()) 
     { 
      object copy = System.Delegate.CreateDelegate(typeof(TNewType), d.Target, d.Method, false); 
      if (copy == null) 
       return false; // one or more can not be converted 
      result = System.Delegate.Combine(result, (System.Delegate)copy); 
     } 
     newDelegate = result as TNewType; 
     return (newDelegate != null); 
    } 
相關問題