Reading this blog post it mentions you can get your DI container to automatically subscribe to events if it implements IHandle<>
. That is exactly what I'm trying to accomplish.
Here is what I have so far.
container.Register(Component
.For<MainWindowViewModel>()
.ImplementedBy<MainWindowViewModel>()
.LifeStyle.Transient
.OnCreate((kernel, thisType) => kernel.Resolve<IEventAggregator>().Subscribe(thisType)));
While this code is successfully subscribing MainWindowViewModel
to receive published messages, come time to actually receive messages nothing happens. If I manually subscribe all works as expected.
Here is my MainWindowViewModel
class.
public class MainWindowViewModel : IHandle<SomeMessage>
{
private readonly FooViewModel _fooViewModel;
private readonly IEventAggregator _eventAggregator;
public MainWindowViewModel(FooViewModel fooViewModel, IEventAggregator eventAggregator)
{
_fooViewModel = fooViewModel;
_eventAggregator = eventAggregator;
//_eventAggregator.Subscribe(this);
_fooViewModel.InvokeEvent();
}
public void Handle(SomeMessage message)
{
Console.WriteLine("Received message with text: {0}", message.Text);
}
}
How can I tell Windsor to automatically subscribe if any class inherits IHandle<>
?
I ended up coming up with this custom facility that subscribes.
public class EventAggregatorFacility : AbstractFacility
{
protected override void Init()
{
Kernel.DependencyResolving += Kernel_DependencyResolving;
}
private void Kernel_DependencyResolving(ComponentModel client, DependencyModel model, object dependency)
{
if(typeof(IHandle).IsAssignableFrom(client.Implementation))
{
var aggregator = Kernel.Resolve<IEventAggregator>();
aggregator.Subscribe(client.Implementation);
}
}
}
Looking at the EventAggregator
class provided by Caliburn.Micro I'm able to see that the subcription is successful, however if another class publishes a message the MainWindowViewModel
class isn't getting getting handled. Manually subscribing still works but I'd like to automate this process. I have a feeling that it's not subscribing the correct instance. Not sure how to fix that, though.
I've also tried using every other event exposed by the Kernel
property. Most of them can't resolve IEventAggregator
.
What am I missing?
"I have a feeling that it's not subscribing the correct instance. Not sure how to fix that, though."
You are subscribing to the type of the implementation (an instance of System.Type), not the actual dependency being resolved. The line:
aggregator.Subscribe(client.Implementation);
should be
aggregator.Subscribe(dependency);
You probably need to configure your IEventAggregator as a singleton. Not sure exactly how this would be done with Windsor, but with ninject you would do something like
Bind<IEventAggregator>().To<ConcreteEventAggregator>().InSingletonScope()
Having a singleton would ensure that all the events are aggregated into a single underlying dictionary (or the data type of your choice), instead of having a new one created every time you resolve IEventAggregator. HTH.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With