用于处理事件订阅的实用程序类(AddSubscription()/UnsubscribeAll())

本文关键字:AddSubscription UnsubscribeAll 实用程序 处理事件 用于 | 更新日期: 2023-09-27 18:01:58

我经常写SubscribeToEvents()UnsubscribeEvents()函数,当一个属性得到一个新值时,在我的属性设置器中调用。虽然这样做的代码很简单,但我觉得没有必要,因为它基本上是重复的代码(代码是相同的,除了+=-=)。

我正试图创建一个小实用程序类,通过具有AddSubscription(EventHandler, EventHandler)函数和UnsubscribeAll()函数来清除AddSubscription注册的所有订阅来处理此问题:

public class EventSubscriber
{
    private readonly List<KeyValuePair<EventHandler, EventHandler>> _subscriptions = new List<KeyValuePair<EventHandler, EventHandler>>();
    public void AddSubscription(EventHandler toSubscribe, EventHandler subscriber)
    {
        toSubscribe += subscriber;
        _subscriptions.Add(new KeyValuePair<EventHandler, EventHandler>(toSubscribe, subscriber));
    }
    public void UnsubscribeAll()
    {
        foreach (KeyValuePair<EventHandler, EventHandler> subscription in _subscriptions)
        {
            EventHandler toSubscribe = subscription.Key;
            EventHandler subscriber = subscription.Value;
            toSubscribe -= subscriber;
        }
        _subscriptions.Clear();
    }
}

然而,我不允许传递事件到AddSubscription():

EventSubscriber subscriber = new eventSubscriber();
subscriber.AddSubscription(_someControl.SomeEvent, OnSomeEvent);

失败,报错

事件'.... .'只能出现在+=或-=

的左侧

有什么办法可以避免这种情况吗?还是我找错对象了?

用于处理事件订阅的实用程序类(AddSubscription()/UnsubscribeAll())

在我看来,如果对象上的事件没有特殊的AddRemove方法,那么您就不走运了。正如你已经学到的,你不能传递事件。
我使用表达式树的想法也不起作用,因为你不允许在表达式树中赋值…

如果您正在使用WPF,并希望将其专门用于WPF控件的事件,您可以使用AddHandlerRemoveHandler方法来实现您的目标,如下所示:

public class EventSubscriber
{
    private readonly List<Tuple<Control, RoutedEvent, Delegate>> 
        _subscriptions = 
            new List<Tuple<Control, RoutedEvent, Delegate>>();
    public void AddSubscription(Control control, RoutedEvent toSubscribe, 
                                Delegate subscriber)
    {
        control.AddHandler(toSubscribe, subscriber);
        _subscriptions.Add(Tuple.Create(control, toSubscribe, subscriber));
    }
    public void UnsubscribeAll()
    {
        foreach (var subscription in _subscriptions)
        {
            subscription.Item1.RemoveHandler(subscription.Item2,
                                             subscription.Item3);
        }
        _subscriptions.Clear();
    }
}

测试。