2011-07-05 96 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); 
    } 
相关问题