Search code examples
c#wpfmvvmcaliburn.microeventaggregator

How to express dependencies explicitly when using Event Aggregator?


This is my first time using an Event Aggregator, so apologies if I'm overlooking or misunderstanding something completely obvious.

  • In my MVVM project, I have multiple model classes that depend on the same, periodically updating data, and they need to react to the changes of the data. (Some of these classes produce their own data based on this dependency, which also need to be sent to yet other classes.)

  • Instead of injecting this same dependency into multiple model classes and using INotifyPropertyChange / PropertyChanged, I want to use Caliburn Micro's EventAggregator to publish and handle the refreshed data.

My concern is that implementing the EventAggregator solution seems to hide the dependencies between various classes, since their explicit dependency will be the EventAggregator.

So, the following in my composition root (obviously just an example code):

_dependency = new Dependency();
_dependent1 = Dependent1(_dependency);
_dependent2 = Dependent2(_dependency);
...

Will become the following, if I'm correct:

_eventAggregator = new EventAggregator();
_dependency = new Dependency(_eventAggregator); // Publishes
_dependent1 = Dependent1(_eventAggregator); // Handles
_dependent2 = Dependent2(_eventAggregator); // Handles
...

Notes:

  • Caliburn Micro contains a generic IHandle<T> interface that can be used to express the handling of certain types of objects.
  • But it doesn't have a corresponsing IPublish<T> interface to explicitly express the publishing of certain types of objects. And even that wouldn't constitute a compile time check for a matching IPublish<T>IHandle<T> pair.
  • Also, my composition root will be hard to read, because it will lack the information about actual dependency hierarchy (which can be substituted by comments, but still).

Solution

  • My concern is that implementing the EventAggregator solution seems to hide the dependencies between various classes, since their explicit dependency will be the EventAggregator.

    Well, that's the purpose of using an event aggregator. All classes only knows about the event aggregator itself but they don't know anything or have any dependencies upon each other. This means that you can modify one class without affecting another one.

    So of course they do have a dependency upon the event aggregator but this is better than keeping a direct reference to each subscriber from each publisher class.

    Obviously the publisher needs to publish an event at some point if the subscriber is dependant on this event somehow. But this is the same even if you have a strong reference to the publisher class from the subscriber.