From PRISM to Caliburn Micro
- 08 Mar, 2011
My team is in the process of transitioning our Silverlight development from Prism to Caliburn Micro. I’ve had questions about how common PRISM scenarios map to Caliburn Micro.
One feature found in most MVVM frameworks is an Event Aggregator. Martin Fowler describes this in his “Further Patterns of Enterprise Architecture”. According to Fowler, the purpose of the Event Aggregator is to simplify event registration by “channeling events from multiple objects into a single object”.
Event Aggregators are most relevant to rich client development, where multiple bits of a composite interface need to share common state. For example, a toolbar, a status bar, a screen, and a notification icon may all need to be synchronized with some common theme that cross cuts the view model approach to state management. Event Aggregators simplify registration and publication of events between objects to some subset of the M * N unique registrations that would be required otherwise.
Event Aggregation in PRISM
In Prism, an event is declare by inheriting from a CompositePresentationEvent
public class FooEvent : CompositePresentationEvent<FooEventArgs> { }
The actual aggregator is called an EventAggregator. It has a single method, GetEvent
Firing an aggregate event from PRISM is simple.
myEventAggregator.GetEvent<FooEvent>().Publish(fooEventArgs);
Subscribing is another matter entirely. Subscribing has up to five parameters including whether to hold a strong or weak reference to the subscriber, which thread to call subscribers on, a filter to determine if the subscriber gets the event, and the delegate to invoke.
The defaults work for most situations and the overloads may create problems. Supporting both strong and weak referencing can lead to confusion.
myEventAggregator.GetEvent<FooEvent>().Subscribe(OnFoo);
Event Aggregation in Caliburn Micro
Event Aggregation in Caliburn Micro is simple. In Caliburn Micro, events are plain old CLR objects (poCo). The event argument payload, if needed, is declared in the event as one or more simple properties.
public class FooEvent { public string myProp; }
To subscribe events of interest, subscribers implements IHandle
public class Foo : IHandle<FooEvent>
{
private IEventAggregator myEventAggregator;
public Foo()
{
myEventAggregator.Subscribe(this);
}
public void Handle(FooEvent message)
{
}
}
This IHandle<T>
approach makes explicit and clear at a glance the relationship between interested subscribers and their subscribed events.
Publication is very straightforward:
myEventAggregator.Publish<FooEvent>(new FooEvent());
Caliburn Micro’s publish model isn’t as powerful as its PRISM counter part. Yet it prevents you from shooting yourself in the foot with good, opinionated defaults; It holds weak references in the event aggregator and executes events on the UI thread.
While some PRISM event scenarios cannot be implemented using the event aggregator in Caliburn Micro, this lack of choice isn’t a deficit. It welcomes us all into the “pit of success.”