繁体   English   中英

如何将事件传递给 C# 中的 function?

[英]How can I pass an event to a function in C#?

我希望将事件传递给助手 function。 此 function 将向事件附加一个方法。 但是,我无法正确通过该活动。 我试过传递一个EventHandler<TEventArgs> 它可以编译,但未附加事件(但仍会添加;似乎制作了事件处理程序的副本)。

例如,如果我有这个:

public event EventHandler<EventArgs> MyEvent;

和助手 function:

public static void MyHelperFunction<TEventArgs>(EventHandler<TEventArgs> eventToAttachTo)
{
    eventToAttachTo += (sender, e) => { Console.WriteLine("Hello world"); };
}

和来电者:

MyHelperFunction(MyEvent);
MyEvent(null, new EventArgs()); // Does nothing.

这不起作用的原因是 += 当应用于委托时会创建一个新委托,它是旧委托和新委托的组合。 它不会修改现有的委托。

为了使它起作用,您必须通过引用传递委托。

public static void Helper(ref EventHandler<EventArgs> e)
{
    e+= (x,y) => {};
}

这在方法之外起作用的原因是因为 LHS 仍然是实际字段。 所以 += 将创建一个新的委托并分配回成员字段。

刚刚想出了这个小帮手。 如果它是您自己创建的事件,您可以使用这样的包装器。 您可以像往常一样使用 += 运算符附加处理程序,但可以传递包装器,甚至可以从其他地方引发事件。

public class GenericEvent<T> where T:EventArgs
{
    public event EventHandler<T> Source = delegate { };

    public void Raise(object sender, T arg = default(T))
    {
        Source(sender, arg);
    }

    public void Raise(T arg = default(T))
    {
        Source(this, arg);
    }

    public void AddHandler(EventHandler<T> handler)
    {
        Source += handler;
    }

    public void RemoveHandler(EventHandler<T> handler)
    {
        Source -= handler;
    }

    public static GenericEvent<T> operator +(GenericEvent<T> genericEvent, EventHandler<T> handler)
    {
        genericEvent.AddHandler(handler);
        return genericEvent;
    }
}

创建事件,如:

public GenericEvent<EventArgs> MyEvent = new GenericEvent<EventArgs>();

附加处理程序:

MyEvent += (s,e) => {};

提升事件:

MyEvent.Raise();

只是猜测:您是否尝试过将其作为参考传递?

public static void MyHelperFunction<TEventArgs>(ref EventHandler<TEventArgs> eventToAttachTo)

MyHelperFunction(ref MyEvent);

这不是很好,但你可以使用反射来做到这一点。

    public EventMonitor(object eventObject, string eventName)
    {
        _eventObject = eventObject;
        _waitEvent = eventObject.GetType().GetEvent(eventName);

        _handler = new EventHandler(SetEvent);
        _waitEvent.AddEventHandler(eventObject, _handler);
    }

其中 eventObject 是包含事件的 object,eventName 是事件的名称。 SetEvent 是您的事件处理程序。

我也有这样的处理方法:

    public void Dispose()
    {
        _waitEvent.RemoveEventHandler(_eventObject, _handler);
    }

传递类似 Action e = e => myevent += e; 并使用处理程序从方法调用? 它具有与 .NET 类一起使用的好处。

我有一个解决方案,我有两个接口。 第一个接口具有绑定某些事件的方法,而另一个接口具有可以绑定到这些事件的事件方法。

第一个接口的绑定方法将第二个接口作为参数,这使得可以将事件绑定到任何实现第二个接口的 class 的事件方法。

这是可以理解的,还是您更喜欢一些代码? :)

正如许多人所指出的,将事件传递给方法要么是不可能的,要么并不简单。

  1. 请澄清,但我怀疑您的预期用途将类似于:

     void Register() { var super = new SuperHandler(); //not valid syntax: super.HandleEvent(MyEvent1); super.HandleEvent(MyEvent2); super.HandleEvent(MyEvent3); super.HandleEvent(MyEvent4); }

    您可以简单地通过使您的预期通用事件处理程序可公开访问(或在内部,如果您愿意)来实现:

     public static class GenericHandler { public static void HandleAnyEvent(object sender, EventArgs e) { //handle } } public class SomeClass { void RegisterEvents() { var r = new EventRaiser(); r.ImportantThingHappened += GenericHandler.HandleAnyEvent; } }

    在此示例中,我的包罗万象的处理程序位于 static class 中,但您也可以使用非静态 class。 另外,我看到在您的示例中,您已将方法设为通用(TEventArgs)。 因为所有 EventHandler 派生类(例如 CancelEventHandler)都与基本 EventHandler 匹配,所以您不需要涉及 generics(也不会有帮助)。

  2. 如果注册逻辑很复杂或者您必须保持 EventHandler 私有,请考虑使用接口事件 这可能无法满足您减少代码量的预期目标,但它将允许您创建一个 class 可以预测地处理特定类型的所有事件。

     interface IRaiseEvents { event EventHandler ConnectionCreated; event EventHandler ConnectionLost; } public class SuperHandler { void RegisterEvents(IRaiseEvents raiser) { raiser.ConnectionCreated += (sender, args) => Console.WriteLine("Connected."); raiser.ConnectionLost += (sender, args) => Console.WriteLine("Disconnected."); } }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM