我有这样的测试:
receivingType.IsAssignableFrom(exportingType))
大部分时间都有效,但当涉及的类型是委托类型时,不会返回所需的结果。例如,如果exportsType为Action<object, EventArgs>
且receivingType为EventHandler
,我希望结果为true,但上面的表达式为false。我正在寻找的结果是true
,因为两个代表具有相同的方法签名,实际上在C#中实际上可以相互分配(尽管我理解这可能是C#语法魔法)。
所以我的问题是,对于能够提供所需兼容性结果的代表,等效测试会是什么样的?
答案 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
测试。