如何通过c#反射来检查一个方法是否可以作为事件的处理程序

本文关键字:是否 事件 程序 处理 方法 一个 反射 何通过 检查 | 更新日期: 2023-09-27 18:16:33

我创建了一个基于事件的系统,其中一个类将提供一堆事件,另一个类及其成员方法可以附加到第一个类作为其事件处理程序,并且…我只是想做这样的事情

if(isMethodCompatibleToEvent(...))
{
    connectMethodToEvent(...)
}

通过反射,连接是这样完成的:

void connectMethodToEvent(object methodTarget, MethodInfo mi,
    object eventTarget, EventInfo ei)
{
    Delegate handler = Delegate.CreateDelegate(ei.EventHandlerType, methodTarget, mi);
    ei.AddEventHandler(eventTarget, handler);
}

如果方法与事件不兼容,它将抛出异常,为了解决这个问题,我想在创建方法委托之前创建一些检查,但是如何呢?

bool isMethodCompatibleToEvent(object methodTarget, MethodInfo mi,
    object eventTarget, EventInfo ei)
{
    // HOW ?
}

如何通过c#反射来检查一个方法是否可以作为事件的处理程序

  • 形式参数个数必须相同
  • 形式参数的"refness"必须相同。(从技术上讲,具有out参数的方法可以用于具有ref参数的事件,反之亦然,但我不建议这样做。)
  • 各形式参数类型必须兼容。对于值类型,它们必须精确匹配。对于引用类型的形式形参,允许有逆变。也就是说,如果你有一个事件处理程序,它将传递一个长颈鹿给委托,委托被允许接受Animal。
  • 返回类型的"void"必须相同;void只匹配void
  • 对于非空返回类型,值类型必须完全匹配。对于返回引用类型的事件处理程序,允许协方差。也就是说,如果事件处理程序说它返回Animal而委托返回Giraffe,那就可以了。

这些不是所有的规则,但它们足以处理绝大多数常见情况

你需要比较方法和委托的签名(定义事件的类型):如果它们匹配,那么方法可以合并到事件中。

参数和返回类型的精确匹配显然是最简单的,但也要考虑隐式转换也可以应用(根据您的需求,使用Type.IsAssignableFrom可能就足够了)。

检查c#语言规范中关于方法和事件类型兼容性的规则将是第一步。