动态地将委托绑定到事件

时间:2013-10-02 08:45:02

标签: c# reflection delegates

我有一个方法可以将页面上的方法绑定到动态创建的LinkButton

protected virtual void AddDynamicHandlerToControl(Page page, Control controlInstance,
            string methodName, string eventName)
{
   Delegate d = null;

   EventInfo ei = controlInstance.GetType().GetEvent(eventName);

   Type tDelegate = ei.EventHandlerType;

   MethodInfo method = page.GetType().BaseType.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);

   if (method != null)
      d = Delegate.CreateDelegate(tDelegate, page, method);
   else {
      FieldInfo field = page.GetType().BaseType.GetField(methodName, BindingFlags.NonPublic | BindingFlags.Instance);

      if (field != null)
      {
         d = field.GetValue(page) as Delegate;
      }
   }

   MethodInfo addHandler = ei.GetAddMethod();
   object[] addHandlerArgs = { d };
   addHandler.Invoke(controlInstance, addHandlerArgs);
}

这适用于该页面内的方法。我想要添加的是对用户控件内部方法的支持。所以我在代码隐藏页面中创建了一个delegate,并在运行时为其分配了用户控件方法。

我像这样创建和分配委托:

protected event PrintPageMethod PrintPage;
protected delegate void PrintPageMethod(object sender, EventArgs e);

然后:

PrintPage = DetailedTestsResult1.UserActionsForTests1_PrintPage;

代码试图找到一个方法,当找不到一个方法时,它会尝试为委托找到一个字段并找到正确的委托,它指向正确的方法,并以用户控件类为目标。

问题在于,当达到addHandler.Invoke(controlInstance, addHandlerArgs);时,它会抛出异常

  

'SomePage + PrintPageMethod'类型的对象无法转换为'System.EventHandler'类型。

我无法弄清楚我做错了什么。

2 个答案:

答案 0 :(得分:1)

而不是:

protected event PrintPageMethod PrintPage;
protected delegate void PrintPageMethod(object sender, EventArgs e);

使用:

protected event EventHandler PrintPage;

尽管有类似的签名,委托类型也不同。

答案 1 :(得分:1)

您无法将委托转发给其他委员。

d = field.GetValue(page) as Delegate;

Delegate orig = field.GetValue(page) as Delegate;
d = Delegate.Combine(
    orig.GetInvocationList()
    .Select(_ => Delegate.CreateDelegate(tDelegate, _.Target, _.Method))
    .ToArray()
    );

您可以使用Delegate.Target中的调用目标创建另一个.Method,如果代理有多个目标,则需要组合每个代理。