Search code examples
c#delegatesprismeventaggregator

Prism EventAggregator Subscribe to delegate that references itself to Unsubscribe


Is it possible to do something like this:

EventHandler handler = null;
handler = (s, args) =>
{
    DoStuff();
    something.SomeEvent -= handler;
};
something.SomeEvent += handler;

with Prism's EventAggregator? ie

Action subscriber = null;
subscriber = () =>
{
    DoStuff();
    EventAggregator.GetEvent<SomeEvent>().Unsubscribe(subscriber);
};
EventAggregator.GetEvent<SomeEvent>().Subscribe(subscriber);

Solution

  • Yes, that will work with Prism's event aggregator, too. It all comes down to comparing delegates for equality in both examples. Refering to a delegate inside of the anyonymous method is not specific to the event aggregator.

    However, you should be aware that while using anonymous methods for this kind of one-time event handling is working, because you hold on to the delegate instance handler or subscriber, subscribing to and unsubscribing from anonymous methods can be quite challenging in more complex scenarios. You should have have a look at these two questions for understanding how delegate comparison works for anonymous methods.

    As alternatives to using an anonymous method, you could either use instance methods or local functions that were introduced in C# 7.0, like in the following example.

    private void AddEventHandler()
    {
       // Local method to replace your anonymous method
       void DoStuffAndUnsubscribe()
       {
          DoStuff();
          eventAggregator.GetEvent<SomeEvent>().Unsubscribe(DoStuffAndUnsubscribe);
       }
    
       eventAggregator.GetEvent<SomeEvent>().Subscribe(DoStuffAndUnsubscribe);
    }
    

    As @Haukinger pointed out, the most concise way is to capture an instance of the subscription token of the event in the anonymous method to unsubscribe using Dispose().

    IDisposable subscriptionToken = null;
    subscriptionToken = eventAggregator.GetEvent<SomeEvent>().Subscribe(() =>
    {
        DoStuff();
        subscriptionToken.Dispose();
    });