我经常写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);
失败,报错
事件'.... .'只能出现在+=或-=
的左侧
有什么办法可以避免这种情况吗?还是我找错对象了?
在我看来,如果对象上的事件没有特殊的Add
和Remove
方法,那么您就不走运了。正如你已经学到的,你不能传递事件。
我使用表达式树的想法也不起作用,因为你不允许在表达式树中赋值…
如果您正在使用WPF,并希望将其专门用于WPF控件的事件,您可以使用AddHandler
和RemoveHandler
方法来实现您的目标,如下所示:
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();
}
}
测试。