开发者

Convert from one delegate to another. Pseudo cast

开发者 https://www.devze.com 2023-03-17 06:40 出处:网络
We are using IoC and have our logging exposed with it. We are using Common.Logging and I have written a matching delegate for Common.Logging.FormatMessageHandler but I do not know how to convert from

We are using IoC and have our logging exposed with it. We are using Common.Logging and I have written a matching delegate for Common.Logging.FormatMessageHandler but I do not know how to convert from our version of that delegate to the one that the Common.Logging api is expecting.

This question appears to be similar but I do not understand how to convert from my implemented type to the known type that I want to call. Dynamically casting one type of delegate to another

Here is my delegate signature:

public delegate string FormatMessageHand开发者_JS百科ler(string format, params object[] args)

Here is Common.Logging's:

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

Same name (not that is matters) and same number of parameters. Both are known at compile time so it should be something obvious but I am not seeing it.


Why are you not using Common.Logging's delegate in the first place if it is exactly the same?

However, a solution to your problem is to either use the dynamic cast explained in the article linked in the question you mentioned, or you do it like this:

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

UPDATE:
According to your comment, you want something like that:

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

This will create a new action with one parameter h of type Common.Logging.FormatMessageHandler which calls the supplied action formatMessageCallback with a new delegate of Your.FormatMessageHandler that accepts two parameters f and a. This new delegate in turn calls h with the two supplied parameters.


Manually you can do this, but it is as expensive as the reflection involved at conversion. Once the delegate is converted it behaves basically the same...

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);
    }
0

精彩评论

暂无评论...
验证码 换一张
取 消