The Prism EventAggregator really is too verbose.
To subscribe to an event you have to
-
Instantiate (or get the current) an instance of
EventAggregator which is somehow complex for itself, especially when you want to use simple MVVM, without Unity or MEF (read note bellow).
-
I was looking around how I can get rid of this verbosity, and fortunately have found this and this great posts that helped me write a simple wrapper that simplifies the verbosity of the Prism EventAggregator system.
Any comments and features will be honestly appreciated!
Another advatage is the possibilty to publish and subscribe to global events without having to worry about parameters and arguments. The event type in this case is only used for indentification (the EA internally stores the event using its type as the dictionary key). sometimes you really need to publish a global event such as "UserLoggedIn" or "ConnectionLost" etc. etc. etc.
Note: If instantiating the EventAggregator is not your concern and you already have a present IEventAggregator instance but just want to skip the CompositePresentationEvent<T> part, then this is for you.
Here is the wrapper (VB.NET version):
public static class EventAggregation
{
private static IEventAggregator _Current;
public static IEventAggregator Current
{
get
{
return _Current ?? (_Current = new EventAggregator());
}
}
private static CompositePresentationEvent<TEvent> GetEvent<TEvent>()
{
return Current.GetEvent<CompositePresentationEvent<TEvent>>();
}
public static void Publish<TEvent>()
{
Publish<TEvent>(default(TEvent));
}
public static void Publish<TEvent>(TEvent @event)
{
GetEvent<TEvent>().Publish(@event);
}
public static SubscriptionToken Subscribe<TEvent>(Action action, ThreadOption threadOption = ThreadOption.PublisherThread, bool keepSubscriberReferenceAlive = false)
{
return Subscribe<TEvent>(e => action(), threadOption, keepSubscriberReferenceAlive);
}
public static SubscriptionToken Subscribe<TEvent>(Action<TEvent> action, ThreadOption threadOption = ThreadOption.PublisherThread, bool keepSubscriberReferenceAlive = false, Predicate<TEvent> filter = null)
{
return GetEvent<TEvent>().Subscribe(action, threadOption, keepSubscriberReferenceAlive, filter);
}
public static void Unsubscribe<TEvent>(SubscriptionToken token)
{
GetEvent<TEvent>().Unsubscribe(token);
}
public static void Unsubscribe<TEvent>(Action<TEvent> subscriber)
{
GetEvent<TEvent>().Unsubscribe(subscriber);
}
}
Usage:
public class Program
{
public static void Main()
{
SubscriptionToken token =
EventAggregation.Subscribe<CustomerEvent>(
ce => Console.WriteLine("Hello {0}!!", ce.Name),
filter: ce => ce.Name.Contains("Weitzhandler")
);
EventAggregation.Publish(new CustomerEvent("Shimmy Weitzmaker"));
EventAggregation.Publish(new CustomerEvent("Shimmy Weitzhandler"));
EventAggregation.Unsubscribe<CustomerEvent>(token);
EventAggregation.Publish(new CustomerEvent("Shimmy Weitzhandler"));
Action<string> action = s => Console.WriteLine(s);
EventAggregation.Subscribe<string>(action);
EventAggregation.Publish("Hello!");
EventAggregation.Unsubscribe(action);
EventAggregation.Publish("Hello!!!");
//Parameterless event:
EventAggregation.Subscribe<UserLoggedInEvent>(()=> Console.WriteLine("User logged in!"));
EventAggregation.Publish<UserLoggedInEvent>();
}
}
public class CustomerEvent
{
public CustomerEvent(string name)
{
_Name = name;
}
private readonly string _Name;
public string Name
{
get { return _Name; }
}
}
Output:
Hello Shimmy Weitzhandler!!
Hello!
User logged in!