具有自定义事件参数的C#反射编程事件处理程序

时间:2011-01-18 11:04:47

标签: c# events reflection

这是我的问题/方案

public class TestEventArgs : EventArgs
{
   public int ID { get; set; }
   public string Name { get; set; }
}

public event EventHandler<TestEventArgs> TestClick

如何使用反射在TestClick上附加EventHandler? (obj是实例,Activator.CreateInstance)

EventInfo eventClick = obj.GetType().GetEvent("TestClick");
Delegate handler = Delegate.CreateDelegate(eventClick.EventHandlerType, obj, ????);
eventClick.AddEventHandler(obj, handler);

我的问题是TestEventArgs是在外部dll中声明的,但是????上面的methodinfo需要在其委托中签名吗?

3 个答案:

答案 0 :(得分:7)

我设法通过遵循以下文章描述的技术来使我的代码工作, http://www.pelennorfields.com/matt/2009/03/13/createdelegate-error-binding-to-target-method/

本质上,如果我执行以下操作,则会收到错误“绑定到目标方法的错误”,

<强> FAIL:

EventInfo eventClick = obj.GetType().GetEvent("TestClick");
Delegate handler = Delegate.CreateDelegate(
    eventClick.EventHandlerType, this, "TestClick");
eventClick.AddEventHandler(obj, handler);

<强> SUCCESS:

但是当我把它改为:

MethodInfo methodOn_TestClick = this.GetType().GetMethod("TestClick", new Type[] { typeof(object), typeof(EventArgs));

Delegate handler = Delegate.CreateDelegate(
    event_DomClick.EventHandlerType, this, methodOn_TestClick, true); // note the change here

eventClick.AddEventHandler(obj, handler);

然后我在TestClick方法中使用了反射,从标准的EventArgs中获取了我需要的属性。

例如。

public void TestClick(object sender, EventArgs e)
{
    PropertyInfo prop_ID = e.GetType().GetProperty("ID");

    int id = Convert.toInt32(prop_ID.GetValue(e, null));
}

答案 1 :(得分:1)

您是否控制目标组件的来源?如果是这样,只需将InternalsVisibleTo程序集属性添加到目标程序集即可。

答案 2 :(得分:-2)

如果您使用了Activator.CreateInstance(),那么您对对象类型的引用是正确的吗?

添加自己的处理程序:

在它上面调用type.GetFields(),现在你已经有了内部字段(如果事件是在基类中定义的,你需要首先使用type.BaseType向上移动到一个等级到达你达到了你需要的水平。

为委托提供FieldInfo实例后,在GetValue()实例上传递对象的事件处理程序调用{​​{1}}。现在,您已获得支持事件处理程序的委托。现在请致电FieldInfo

我很确定使用Delegate.Combine你只需要确保事件处理程序的签名匹配,而不是实际类型。因此,使用相同的签名创建自己的委托应该足够了。