如何手动调用事件?

Jes*_*aya 22 c# events

我在C#中有以下行:

_timer.ElapsedTick += _somefunction1;
_timer.ElapsedTick += _somefunction2;
_timer.ElapsedTick += _somefunction3;
Run Code Online (Sandbox Code Playgroud)

如何在不指定_somefunction的情况下调用订阅_timer.ElapsedTick的所有方法?沿着这条伪线的某个地方

invoke(_timer.ElapsedTick);
Run Code Online (Sandbox Code Playgroud)

非常感激您的帮忙.

更新

@ M.Babcock的例子正在发挥作用.FireEvent方法具有魔力.谢谢.

class InvokeFromMe
{
    public event EventHandler RaiseMe;
}
class MainClass
{
    public MainClass()
    {
        InvokeFromMe fromMe = new InvokeFromMe();
        fromMe.RaiseMe += fromMe_RaiseMe;
        fromMe.RaiseMe += fromMe_RaiseMe1;
        FireEvent(fromMe, "RaiseMe", null, EventArgs.Empty);
        //works

        System.Timers.Timer _timer = new System.Timers.Timer();
        _timer.Elapsed += _timer_Elapsed;
        FireEvent(_timer, "onIntervalElapsed", null, null);
        //throws exception
    }
    private void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        Console.WriteLine("_timer_Elapsed raised");
    }
    private void fromMe_RaiseMe(object sender, EventArgs e)
    {
        Console.WriteLine("Event Handler 0 Raised");
    }
    private void fromMe_RaiseMe1(object sender, EventArgs e)
    {
        Console.WriteLine("Event Handler 1 Raised");
    }
    public void FireEvent(object onMe, string invokeMe, params object[] eventParams)
    {
        MulticastDelegate eventDelagate =
              (MulticastDelegate)onMe.GetType().GetField(invokeMe,
               System.Reflection.BindingFlags.Instance |
               System.Reflection.BindingFlags.NonPublic).GetValue(onMe);

        Delegate[] delegates = eventDelagate.GetInvocationList();

        foreach (Delegate dlg in delegates)
        {
            dlg.Method.Invoke(dlg.Target, eventParams);
        }
    }
}
class Program
{
    static void Main(string[] args)
    {
        MainClass m = new MainClass();
    }
}
Run Code Online (Sandbox Code Playgroud)

Jar*_*Par 20

您不能调用由其他类型拥有的事件.事件只能从声明它的类内部调用.

  • @MatthewPatrickCashatt*general*在回答"你怎么用C#做这个"的问题时,我限制了我对没​​有反射/ pinvoke/COM互操作的语言可以做什么的答案.这些通常是代码库中的禁忌,因此通常不正确*.一旦你带来了反射,有很多东西是可能的,而这些反射根本无法用C#完成,并且通常有充分的理由.例如,允许您为我调用我的事件是危险的.它可以很容易地打破我的消费者所依赖的微妙保证(例如预订最终事件). (7认同)
  • @MatthewPatrickCashatt是的,但你正在使用反思.这可以用来解决CLR和C#中的大量限制.一般来说,我不认为反射是"我怎么做X"的有效答案.它绝对有效 (5认同)
  • @MatthewPatrickCashatt这绝不是一个强硬的规则,也不是普遍认同的.这是我回答问题的方法.如果你仔细观察我的历史,我相信你可以找到许多我决定抛出反思答案的地方.我一般会告诉我的答案虽然"不太可能在香草C#中,但如果你想弄脏你的手"...... (2认同)
  • @MatthewPatrickCashatt你是对的我应该更加小心地说它"不起作用"当它"它确实有效但你可能不应该这样做". (2认同)

M.B*_*ock 20

可以使用传统的C#完成吗?不(如前所述).但使用反射是可能的.以下是基于此MSDN论坛帖子的答案的一些经过测试的代码:

class InvokeFromMe
{
    public event EventHandler RaiseMe;
}

class Program
{
    static void Main(string[] args)
    {
        var fromMe = new InvokeFromMe();

        fromMe.RaiseMe += fromMe_RaiseMe;
        fromMe.RaiseMe += fromMe_RaiseMe1;
        fromMe.RaiseMe += fromMe_RaiseMe2;

        FireEvent(fromMe, "RaiseMe", null, EventArgs.Empty);
    }

    static void fromMe_RaiseMe(object sender, EventArgs e)
    {
        Console.WriteLine("Event Handler 0 Raised");
    }
    static void fromMe_RaiseMe1(object sender, EventArgs e)
    {
        Console.WriteLine("Event Handler 1 Raised");
    }
    static void fromMe_RaiseMe2(object sender, EventArgs e)
    {
        Console.WriteLine("Event Handler 2 Raised");
    }

    public static void FireEvent(object onMe, string invokeMe, params object[] eventParams)
    {
        MulticastDelegate eventDelagate =
              (MulticastDelegate)onMe.GetType().GetField(invokeMe,
               System.Reflection.BindingFlags.Instance |
               System.Reflection.BindingFlags.NonPublic).GetValue(onMe);

        Delegate[] delegates = eventDelagate.GetInvocationList();

        foreach (Delegate dlg in delegates)
        {
            dlg.Method.Invoke(dlg.Target, eventParams);
        }
    } 

}
Run Code Online (Sandbox Code Playgroud)

UPDATE

我不熟悉这门System.Timer.Timer课程,所以我不确定与我提供的例子有什么不同.您也许可以尝试以下方法:

public static void FirePublicEvent(object onMe, string invokeMe, params object[] eventParams)
{
    MulticastDelegate eventDelagate =
          (MulticastDelegate)onMe.GetType().GetField(invokeMe,
           System.Reflection.BindingFlags.Instance |
           System.Reflection.BindingFlags.Public).GetValue(onMe);

    Delegate[] delegates = eventDelagate.GetInvocationList();

    foreach (Delegate dlg in delegates)
    {
       dlg.Method.Invoke(dlg.Target, eventParams);
    }
} 
Run Code Online (Sandbox Code Playgroud)

  • 我将`System.dll`带入了ILSpy并对该事件进行了逆向工程.像Reflector,ILSpy和JustDecompile这样的工具是.NET开发人员工具箱的必备工具. (2认同)

Dan*_*ish 6

好吧,我最终在这里搜索如何简单地启动事件,它没有任何自定义参数或任何东西。我知道 OP 问题是不同的!但我想分享,我希望它可以帮助某人。

非简化版:

 var Handler = EventNameHere;
        if (Handler != null)
        {
            Handler(this, EventArgs.Empty);
        }
Run Code Online (Sandbox Code Playgroud)

简化版:

 EventNameHere?.Invoke(this, EventArgs.Empty);
Run Code Online (Sandbox Code Playgroud)