如何检测委托类型之间的兼容性?

时间:2014-04-15 05:27:32

标签: c# types delegates

我有这样的测试:

receivingType.IsAssignableFrom(exportingType))

大部分时间都有效,但当涉及的类型是委托类型时,不会返回所需的结果。例如,如果exportsType为Action<object, EventArgs>且receivingType为EventHandler,我希望结果为true,但上面的表达式为false。我正在寻找的结果是true,因为两个代表具有相同的方法签名,实际上在C#中实际上可以相互分配(尽管我理解这可能是C#语法魔法)。

所以我的问题是,对于能够提供所需兼容性结果的代表,等效测试会是什么样的?

2 个答案:

答案 0 :(得分:3)

如果您选择忽略参数/返回类型协方差/逆变(自C#2.0以来编译器支持的方差和与in / out的一般协变/逆变),要求均等类型,您可以使用:

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

(如评论中所述,您可能还想检查out / ref参数......)

答案 1 :(得分:0)

原来,以下对我来说效果很好。虽然我没有验证它处理泛型类型arg协方差和所有复杂性,但我怀疑它确实如此,我没有必要做任何事情。 :)

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测试。