代码之家  ›  专栏  ›  技术社区  ›  Jason Coyne

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

  •  3
  • Jason Coyne  · 技术社区  · 16 年前
    public class a
    {
       public event eventhandler test;
       public void  RaiseTest(){//fire test}
    }
    

    是否可以在不调用该方法的情况下从该类外部引发该类上的测试?

    基本上,我有大量必须基于外部源引发的事件,不想为每个事件创建一个Raise()函数。

    是否可以创建一个泛型Raise(),将要引发的事件作为参数接受?因此它仍然会从类内部调用?

    2 回复  |  直到 16 年前
        1
  •  5
  •   Reed Copsey    16 年前

    你可以通过反射来做到这一点,但这并不明显。如果在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 }); 
    }
    

    请注意,这需要从实例获取非公共字段,因此它只能在完全信任的情况下工作,并且非常有限。

    对要做到这一点,修改上述代码将相当容易。用这个替换“myClassInstance”。这实际上也将允许它在完全信任的情况下正常工作,因为非公共绑定标志不再是一个问题。

        2
  •  1
  •   Thomas Levesque    16 年前

    是否可以在不调用该方法的情况下从该类外部引发该类上的测试?

    简短回答:没有。

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

    是否可以创建一个泛型Raise(),将要引发的事件作为参数接受?因此它仍然会从类内部调用?

    我不这么认为,至少不容易。。。即使使用反射,也没有 EventInfo.Invoke 方法好的,引发事件的唯一方法是从类内部静态地引发事件

    编辑:实际上这是可以做到的(见里德的答案),但有一个限制,即应用程序必须在完全信任的情况下运行。