开发者

Utility class for handling event subscriptions (AddSubscription()/UnsubscribeAll())

开发者 https://www.devze.com 2023-03-20 09:29 出处:网络
I frequently end up writing SubscribeToEvents() and UnsubscribeEvents() functions that are called in my property setters when a property gets a new value. Although the code to do this is quite simple

I frequently end up writing SubscribeToEvents() and UnsubscribeEvents() functions that are called in my property setters when a property gets a new value. Although the code to do this is quite simple it feels unnecessary to me as it's basicly duplicates the code (code is the same except from += and -=).

I'm trying to create a small utility class that handles this by having a AddSubscription(EventHandler, EventHandler) function and an UnsubscribeAll() function that clears all subscriptions registered by AddSubscription:

public class EventSubscriber
{
    private readonly List<KeyValuePair<EventHandler, EventHandler>> _subscriptions = new List<KeyValuePair<EventHandler, EventHandler>>();

    public void AddSubscriptio开发者_JAVA百科n(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();
    }
}

However, I'm not allowed to pass events in to AddSubscription():

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

This fails with error

The event '....' can only appear on the left hand side of += or -=

Is there any way I can avoid this, or am I barking up the wrong tree?


As I see it, you are out of luck if there are no special Add and Remove methods for the events on your object. As you already learned, you can't pass the event.
My idea using an expression tree doesn't work either, because you are not allowed to have assignments in an expression tree...

If you are using WPF and want to use this specifically for your WPF control's events, you can use the methods AddHandler and RemoveHandler to achieve your goal, like so:

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();
    }
}

Untested.

With WinForms you are out of luck again.

0

精彩评论

暂无评论...
验证码 换一张
取 消