How to determine compatibility between types of delegates?

I have a test like this:

receivingType.IsAssignableFrom(exportingType))

It works most of the time, but does not return the desired result when types include delegate types. For example, if exportingType is relevant Action<object, EventArgs>and receiveType is EventHandler, I want the result to be true, but the above expression is false. The result I'm looking for is truebecause the two delegates have equivalent method signatures, and in fact in C # they are actually assigned to each other (although I understand that C # is probably the syntactic magic).

So my question is: what would an equivalent test look like for delegates that would provide the desired compatibility result?

+4
source share
2 answers

If you decide to ignore the covariance / contravariance of the parameter / return type (both the variance supported by the compiler with C # 2.0 and the general covariant / contravariance with in/ out), requiring only equality of types, you could

public static bool AreCompatible(Type delegate1, Type delegate2)
{
    MethodInfo method1 = delegate1.GetMethod("Invoke");
    MethodInfo method2 = delegate1.GetMethod("Invoke");

    return method1.ReturnType == method2.ReturnType &&
           method1.GetParameters().Select(p => p.ParameterType)
                  .SequenceEqual(method2.GetParameters()
                                         .Select(p => p.ParameterType));
}

(As noted in the comments, you can also check the output parameters / ref ...)

+3
source

It turned out that the following works very well for me. Although I have not yet confirmed that it handles arg covariance of a general type and all this complexity, I suspect that it is, and I did not need to do anything. :)

internal static bool IsAssignableFrom(Type importingDelegate, Type exportingDelegate)
{
    Type importingDelegate, exportingDelegate; // assigned elsewhere
    MethodInfo exportingDelegateMethod = exportingDelegate.GetMethod("Invoke");
    try
    {
        exportingDelegateMethod.CreateDelegate(importingDelegate, null);
        return true;
    }
    catch (ArgumentException)
    {
        return false;
    }
}

, Type.GetMethod , Type.GetRuntimeMethod, , . , .

MethodInfo , GetMethod CreateDelegate.

0

Source: https://habr.com/ru/post/1536534/


All Articles