IEventAggregator appears to be superfluous

Oct 18, 2008 at 1:52 AM
Edited Oct 18, 2008 at 2:01 AM

Problem:
My application has a shell with documents similar to Visual Studio. Each document consists from views. Views within the document communicate with each other through events, e.g. selection change. Views from different documents are isolated and do not see events from other documents. There are also a shell level global events that are to be visible to all the views in all the documents, e.g. options change.

Solution 1. EventAggregator.
There is a global EventAggregator that contains global events. Each document creates its own local EventAggregator to contain domestic events. All views have to know about 2 EventAggregators and work with them appropriately:

localEventAggregator<SelectionEvent>.Subscribe(...);
globalEventAggregator<OptionsEvent>.Subscribe(...);

Obviously, this solution does not scale good enough. What if the application has 3 levels of composition? What if 4?

Solution 2. No EventAggregator.
There is a global UnityContainer for the shell that contains events among the other stuff. Each document creates its own UnityContainer to contain domestic events. All views receive their events through injection as needed:

// shell
this.container.RegisterType<OptionsEvent>(ContainerControlledLifetime());
// document
this.container.RegisterType<SelectionEvent>(ContainerControlledLifetime());
// view ctor
public MyView(OptionsEvent optionsEvent, SelectionEvent selectionEvent...)
{
 optionsEvent.Subscribe(...);
 selectionEvent.Subsribe(...);
}

This solution scales without pain. Events hierarchy or scope is managed in a unified way with the other entities. Views know nothing about outer world structure. I can redesigne my shell or re-use my views in any other shell application.

Conclusion:
From the above I'm making a conclusion that EventAggregator is actually a lame UnityContainer with custom name.
Please point me where I'm wrong.

Thanks,
Andrey.

 

Oct 21, 2008 at 1:55 PM
Edited Oct 21, 2008 at 6:02 PM

Hi, Andrey

 

The EventAggregator provides you a service for publishing and subscribing to events without the need of instantiating and registering events. It is primarily a container for events (it keeps a collection of the events in the system), but relieves the publisher or subscriber from needing to determine whether the event is available. Moreover, it is responsible for locating or building events (the EventAggregator will construct the event on its first access if it has not already been constructed). So, the event will be built upon subscription or publication, allowing the publisher to fire the event without knowing if the event has been created or if there are any subscribers attached, and allowing the subscriber to attach a handler to the event without knowing if the event has already been created.

 

Regarding the described problem, if the views contained in a document need to get the events that only its parent document publishes, you may provide a filter to generate that scope. For example:

myEventAggregator.GetEvent<SomeEvent>().Subscribe(OnSomeEvent, ThreadOption.PublisherThread, true, somePayload => IsInContext(somePayload));

 

bool IsInContext(SomePayload something)

{

    //TODO: Add the logic to determinate if the event should be executed in the current context (e.g.: if the View is in the document).

}

 

void OnSomeEvent(SomePayload something)

{

     //TODO: Add the logic to handle the event.

}


 

In addition, the team considered that kind of scoping you are mentioning, but, as it was not a main scenario (regarding users’ feedback), it was not implemented to keep simplicity.

 

 

 

For more information on the EventAggregator, you may have a look at this topic of the help: Event Aggregator.

 

Hope it helps.

 

Ignacio Baumann Fonay

http://blogs.southworks.net/ibaumann/

Oct 21, 2008 at 5:47 PM
Hi Ignacio,

Thanks for you response. You answered my question. Here is some comment or feedback if you wish :)

1. If I replace word "EventAggregator" with "UnityContainer" in the first paragraph of you post - nothing will change. UnityContainer also takes the burden of building and registering its entities etc. (and it is much more powerful in this regard).

2. Yes, I understand that event filter can be used to emulate scopes. However, I do not see why I would want to emulate if I can take it off-the-shelf with UnityContainer. Moreover, it makes the views in my example tightly bound. We have a family of products where we re-use UI controls and compose them in various ways. That means I will have to write a scope fitter service for each of the use case. Too much.

3. Your note about considering and discarding the scope feature for event makes perfect sense for me. It verifies that my understanding is correct, however feature was not implemented deliberately. I do understand that it is all about prioritization of feature based on the community needs. What seems not right for me is that EventAggregator is trying to implement the things that are already implemented by UnityContainer and its implementation is much weaker. May be instead of investing into EventAggregator duplicate functionality there should be event management unity extension?

Thanks again,
Andrey.



Developer
Oct 24, 2008 at 4:34 PM
Edited Oct 24, 2008 at 4:34 PM
Andrey,

You are right, there is a small bit of what a container would do in EventAggregator, although we have no intention of making it a container.  We did considered relying on the container to handle these events, but we ended up not going this direction for a few reasons:

*  We did not want to require a container to use EventAggregator.  People could then use EventAggregator in situations where they weren't interested in using a container.
*  We did not want to required the user to configure events before they were used.  Such as registering the types with ContainerControlledLifetime to ensure only one exists in the container.
*  We did not want to have to write container-specific pieces to support the events.  We could have used this to solve the registration problems, but did not want container specific pieces.

However, I see no reason you could not use a container for this if it fits your scenarios better. 

Thanks,

-b


Oct 25, 2008 at 11:46 PM
Yes, these considerations make good sense for me. 
The really good thing is that all the event specific functionality resides in EventBase class so that one can easily re-compose a new event aggregation sub-system based on the specific needs as in my case. 

Thank you guys for your time answering my question!
Andrey.