如何使用反射将事件处理程序附加到事件?

Man*_*ani 8 c# reflection events delegates event-handling

我知道EventInfo.AddEventHandler(...)可以用来将处理程序附加到事件的方法.但是,如果我甚至无法定义事件处理程序的正确签名,应该怎么做,因为我甚至没有引用处理程序所期望的事件args?

我将用正确的代码解释问题.

//当我在我的解决方案中提供所有可用的场景时,Zero Reflection Scenario.

internal class SendCommentsManager
{
    public void Customize(IRFQWindowManager rfqWindowManager)
    {
        rfqWindowManager.SendComment += HandleRfqSendComment;
    }

    private void HandleRfqSendComment(object sender, SendCommentEventArgs args)
    {
        args.Cancel = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我希望通过使用反射来实现相同的目标.我已经能够找出大部分内容,但是当我将一个委托附加到事件(使用AddEventHandler)时,它会抛出"Error binding to target method."异常.

我理解这个异常背后的原因,将一个错误的委托附加到一个事件.但必须有一些方法来实现这一目标.

 internal class SendCommentsManagerUsingReflection
 {
     public void Customize(IRFQWindowManager rfqWindowManager)
     {
         EventInfo eventInfo = rfqWindowManager.GetType().GetEvent("SendComment");
         eventInfo.AddEventHandler(rfqWindowManager, 
             Delegate.CreateDelegate(eventInfo.EventHandlerType, this, "HandleRfqSendComment"));
         //<<<<<<<<<<ABOVE LINE IS WHERE I AM GOING WRONG>>>>>>>>>>>>>>
     }

     private void HandleRfqSendComment(object sender, object args)
     {
         Type sendCommentArgsType = args.GetType();
         PropertyInfo cancelProperty = sendCommentArgsType.GetProperty("Cancel");
         cancelProperty.SetValue(args, true, null);
     }
 }
Run Code Online (Sandbox Code Playgroud)

Tho*_*que 12

我认为你的代码失败了,因为它HandleRfqSendComment是私有的.相反,您可以直接创建该方法的委托,而无需将其名称传递给CreateDelegate.然后,您需要使用以下方法将委托转换为所需的类型:

public static Delegate ConvertDelegate(Delegate originalDelegate, Type targetDelegateType)
{
    return Delegate.CreateDelegate(
        targetDelegateType,
        originalDelegate.Target,
        originalDelegate.Method);
}
Run Code Online (Sandbox Code Playgroud)

在您的代码中,您可以使用此方法,如下所示:

EventInfo eventInfo = rfqWindowManager.GetType().GetEvent("SendComment");
Action<object, object> handler = HandleRfqSendComment;
Delegate convertedHandler = ConvertDelegate(handler, eventInfo.EventHandlerType);
eventInfo.AddEventHandler(rfqWindowManager, convertedHandler);
Run Code Online (Sandbox Code Playgroud)