是否可以通过单个方法调用取消订阅多个事件?

时间:2017-11-24 15:58:25

标签: c# events

以下是一个场景:

我有一个订阅许多不同活动的课程:

ProviderOfFruit.Event += OnFruitHarvested;
ProviderOfCars.Event += OnCarBrokeDown;
ProviderOfPeople.Event += OnPersonAwoke;
...etc

后来我想同时取消订阅所有这些内容。 我注定要完整地写出这个:

ProviderOfFruit.Event -= OnFruitHarvested;
ProviderOfCars.Event -= OnCarBrokeDown;
ProviderOfPeople.Event -= OnPersonAwoke;
...etc

或者有没有办法按照以下方式做点什么:

ListOfEvents.Unsubscibe(); ?

注意:我不想清除所有订阅者的事件,我订阅了许多类的活动。我只想让其中一个类取消订阅它订阅的事件。 这里的目标是我永远不会忘记取消订阅特定事件。

2 个答案:

答案 0 :(得分:0)

是的,你可以保留一个类在一个集合中订阅的所有事件并循环它们。这使您不必在订阅期间列出每个事件,然后在取消订阅时再次列出 - 并且,作为奖励,有助于防止在一个地方或另一个地方错过事件的可能性。

然而,这是有限的,并没有解决你的班级对这么多其他班级有很强依赖性的最大问题。您的示例并未提供足够的详细信息,但您可能会发现Event Aggregator使用模式。

答案 1 :(得分:-1)

您可以使用以下模式。首先创建一个类,它将运行你在构造上传递的任意函数,另一个在dispose上运行:

public class EventSubscription : IDisposable {
    private readonly Action _unsubscribe;

    private EventSubscription(Action subscribe, Action unsubscribe) {
        _unsubscribe = unsubscribe;
        subscribe();
    }

    public static IDisposable Create(Action subscribe, Action unsubscribe) {
        return new EventSubscription(subscribe, unsubscribe);
    }

    public void Dispose() {
        _unsubscribe();
    }
}

然后在您订阅活动的班级中创建字段:

private static readonly List<IDisposable> _subscriptions = new List<IDisposable>();

订阅如下:

_subscriptions.Add(EventSubscription.Create(
    () => Event1 += OnEvent1, 
    () => Event1 -= OnEvent1));
_subscriptions.Add(EventSubscription.Create(
    () => Event2 += OnEvent2, 
    () => Event2 -= OnEvent2));

如果您需要取消订阅,请执行以下操作:

_subscriptions.ForEach(c => c.Dispose());

优点包括一次取消订阅,忘记取消订阅的机会要少得多,因为您总是在同一个电话中成对传递+=-=处理程序。

这是一般目的类的变体:

public class Disposable : IDisposable {
    private readonly Action _action;
    private Disposable(Action action) {
        _action = action;
    }
    public static IDisposable FromAction(Action action) {
        return new Disposable(action);
    }
    public void Dispose() {
        _action();
    }
}

你可以在许多地方找到它(比如.NET反应扩展),但如果没有 - 你可以自己实现。然后上面的代码变成:

Event1 += OnEvent1;
_subscriptions.Add(Disposable.FromAction(() => Event1 -= OnEvent1));

当然不需要使用IDisposable,您可以只列出操作列表。