从一个代表转换到另一个代表。伪铸

时间:2011-07-05 21:15:10

标签: c# .net delegates

我们正在使用IoC并使用它公开我们的日志记录。我们正在使用Common.Logging,我为Common.Logging.FormatMessageHandler编写了一个匹配的委托,但我不知道如何将该委托的版本转换为Common.Logging api期望的版本。< / p>

这个问题似乎很相似,但我不明白如何从我的实现类型转换为我想要调用的已知类型。 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)

相同的名称(不重要)和相同数量的参数。两者在编译时都是已知的,所以它应该是明显的,但我没有看到它。

2 个答案:

答案 0 :(得分:8)

如果它完全相同,你为什么不首先使用Common.Logging的委托呢? 但是,解决问题的方法是使用您提到的问题中链接的文章中解释的动态强制转换,或者您这样做:

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

<强>更新
根据你的评论,你想要这样的东西:

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

这将使用h类型的Common.Logging.FormatMessageHandler参数创建一个新操作,该参数使用formatMessageCallback的新委托调用提供的操作Your.FormatMessageHandler,该委托接受两个参数{{ 1}}和f。这个新代表依次使用提供的两个参数调用a

答案 1 :(得分: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);
    }