Reputation: 10482
I have decided to build my own event aggregator for a winforms MVP application I am writing. The purpose is to allow views (user controls) to subscribe to events from models that otherwise have their views.
The question is; since there should be one common event aggregator, and the aggregator is only needed when composing the application of user controls that should interact, then what is the best way of exposing the event aggregator?
My suggestions so far:
Do you have some ideas to help me along?
Upvotes: 0
Views: 1942
Reputation: 571
I had implemented a simple EventBroker for such a scenario. However, I don't think injecting would be a mess. Infact, injecting it to the container and then resolving to publish/subscribe would be the neatest way. Would be easier to unit test as well. My Event Broker is given below (I am using MEF, bu this will hardly make any difference):-
[Export]
public class MyEventBroker : IMyEventBroker
{
[ImportingConstructor]
public MyEventBroker()
{
}
private readonly ConcurrentDictionary<Type, List<Action<CompositeEventArguments>>> _compositeEventHandlers = new ConcurrentDictionary<Type, List<Action<CompositeEventArguments>>>();
public void Publish<T>(CompositeEventArguments args)
{
if (_compositeEventHandlers.ContainsKey(typeof (T)))
{
_compositeEventHandlers[typeof(T)].ForEach(subscriber=> { if (subscriber != null) subscriber.Invoke(args); }); //TODO : check for null. QUES - Will we need weak references?????
}
}
public void Subscribe<T>(Action<CompositeEventArguments> handler)
{
if (!_compositeEventHandlers.ContainsKey(typeof (T)))
_compositeEventHandlers[typeof(T)] = new List<Action<CompositeEventArguments>>();
_compositeEventHandlers[typeof (T)].Add(handler);
}
public void UnSubscribe<T>(Action<CompositeEventArguments> handler)
{
if (_compositeEventHandlers.ContainsKey(typeof (T)))
_compositeEventHandlers[typeof (T)].Remove(handler);
}
}
public class CompositeEvent<T> where T : CompositeEventArguments
{
}
public class CompositeEventArguments
{
}
Now to have your custom event, define your event args:-
#region Custom Events
public class MyCustomEventArgs : CompositeEventArguments{}
#endregion
Then to publish:-
var broker = MefContainer.Instance.Resolve<MyEventBroker>();
broker.Publish<MyCustomEventArgs >(new MyCustomEventArgs());
And to subscribe:-
var broker = MefContainer.Instance.Resolve<MyEventBroker>();
broker.Subscribe<MyCustomEventArgs >(t=>MyHandler(t));
MefContainer is my custom singleton class to expose the composition container. You can use unity, windsor or whatever you like!
Blogged about this here: http://compositewinform.blogspot.co.uk/2014/04/have-you-ever-found-yourself-in.html
Upvotes: 0