【问题标题】:c# dynamic event subscription and unsubscriptionc#动态事件订阅和退订
【发布时间】:2021-02-24 12:16:51
【问题描述】:

我希望能够让一个对象将其方法之一添加到传递给它的EventHandler,并赋予所述方法从EventHandler 中删除自身的能力。

public class EventRaiser {
    public event EventHandler event1
    public event EventHandler event2
    public void fire() {
        event1?.Invoke(this, null);
        event2?.Invoke(this, null);
    }
}

public class EventSubscriber {
    EventHandler eh;
    public EventSubscriber(EventHandler eh) {
        this.eh = eh;
        eh += receive;
    }

    public void receive(object obj, EventArgs data) {
        // Do stuff.
        if(condition) eh -= receive;
    }
}

public class MainClass {
    public void Main() {
        EventRaiser er = new EventRaiser();
        EventSubscriber es1 = new EventSubscriber(er.event1);
        EventSubscriber es2 = new EventSubscriber(er.event2);
        er.fire();
    }
}

上面的代码无法编译,因为我什至无法将er.event1er.event2 传递给EventSubscriber(“事件只能出现在+=...的左侧”)。从EventHandlers 中删除event 关键字可解决此问题,但取消订阅无法正常工作。有没有办法使这项工作?可以使用指针吗?

【问题讨论】:

  • 我认为你不应该甚至可以绕过事件本身。

标签: c# dynamic eventhandler


【解决方案1】:

这里的问题来自你传递了一个EventHandler,而不是包含delegates 的列表本身。基本上是处理程序的“方法指针列表”。

如您所见,在event1 的声明中,您有关键字event,当您将它传递到其他地方时,它会丢失。 不幸的是,您无法轻松提取event 的“delegate 持有者”。

基本上,当您想将处理程序注册到某个事件时,您不知何故需要对其进行编译时引用,以便能够对其进行+=-=

您可以执行以下操作:

public class EventRaiser
{
    public delegate void Event1(string args);
    public List<Event1> handlers = new List<Event1>();

    public void register(Event1 handler)
    {
        handlers.Add(handler);
    }

    public void unregister(Event1 handler)
    {
        handlers.Remove(handler);
    }
    
    public void fire()
    {
        handlers.ForEach(handler => handler("myEventArgs"));
    }
}
public class EventSubscriber
{
    Action<Event1> registerAction;
    Action<Event1> unregisterAction;
    public EventSubscriber(Action<Event1> register, Action<Event1> unregister)
    {
        registerAction = register;
        unregisterAction = unregister;
        registerAction(receive);
    }

    public void receive(string args)
    {
        // Do stuff.
        unregisterAction(receive);
    }
}
public class MainClass
{
    public void Main()
    {
        EventRaiser er = new EventRaiser();
        EventSubscriber es1 = new EventSubscriber(er.register, er.unregister);                
        er.fire();
    }
}

【讨论】:

    猜你喜欢
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多