如何检测委托类型之间的兼容性
本文关键字:类型 之间 兼容性 何检测 检测 | 更新日期: 2023-09-27 17:58:32
我有一个这样的测试:
receivingType.IsAssignableFrom(exportingType))
这在大多数情况下都有效,但当涉及的类型是委托类型时,不会返回所需的结果。例如,如果exportingType是Action<object, EventArgs>
,receivingType是EventHandler
,我希望结果为true,但上面的表达式为false。我要寻找的结果是true
,因为这两个委托具有等效的方法签名,并且事实上在C#中实际上是可以相互分配的(尽管我知道这可能是C#语法的魔力)。
因此,我的问题是,对于能够提供所需兼容性结果的委托,等效测试会是什么样子?
如果您选择忽略参数/返回类型协变/逆变换(自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参数…)
事实证明,下面的方法对我来说非常有效。虽然我还没有验证它是否能处理泛型类型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
测试。