是否可以在没有自定义函数的情况下从该对象外部引发对象上的事件

时间:2009-08-04 22:26:56

标签: c# events raise

public class a
{
   public event eventhandler test;
   public void  RaiseTest(){//fire test}
}

是否可以在此类之外对此类进行测试,而无需调用方法?

基本上我有很多事件必须根据外部源引发,并且不想为每个事件创建一个Raise()函数。

是否可以创建一个通用的Raise()来接受要作为参数引发的事件?因此它仍然会从课堂内召唤?

2 个答案:

答案 0 :(得分:5)

你可以通过Reflection来做到这一点,但它不是那么明显。如果在C#中声明一个事件,则会将一个字段添加到具有事件名称+“Event”的类中。如果在字段上调用GetValue,它将返回MulticastDelegate实例。

拥有MulticastDelegate后,您可以获取调用列表,并依次调用每个成员:

EventArgs e = new EventArgs(myClassInstance);  // Create appropriate EventArgs

MulticastDelegate eventDelagate = 
    this.GetType().GetField(theEventName + "Event",
    System.Reflection.BindingFlags.Instance | 
    System.Reflection.BindingFlags.NonPublic).GetValue(myClassInstance) as MulticastDelegate;

Delegate[] delegates = eventDelagate.GetInvocationList();
foreach (Delegate del in delegates) {  
      del.Method.Invoke(del.Target, new object[] { myClassInstance, e }); 
}

请注意,这需要从实例中获取NonPublic字段,因此它只能完全信任,并且非常有限。

  

是否可以创建一个通用的Raise()来接受要作为参数引发的事件?因此它仍然会从课堂内召唤?

是。修改上面的代码来执行此操作相当容易。用这个替换“myClassInstance”。这实际上允许它在完全信任下正常工作,因为NonPublic BindingFlag将不再是一个问题。

答案 1 :(得分:1)

  

是否可以在此类之外对此类进行测试,而无需调用方法?

简答:不。

只有声明该事件的类才能引发它

  

是否可以创建一个通用的Raise()来接受要作为参数引发的事件?因此它仍然会从课堂内召唤?

我不这么认为,至少不容易......即使使用反射,也没有EventInfo.Invoke方法。 AFAIK,提升事件的唯一方法是在课堂内静态提升

编辑:实际上它可以完成(参见里德的答案),但有限制,即应用必须完全信任。