Using Windsor to automatically subscribe to a custom event aggregator

Reading this blog post that mentions that you can force your DI container to automatically subscribe to events if it implements IHandle<> . This is exactly what I'm trying to accomplish.

Here is what I still have.

 container.Register(Component .For<MainWindowViewModel>() .ImplementedBy<MainWindowViewModel>() .LifeStyle.Transient .OnCreate((kernel, thisType) => kernel.Resolve<IEventAggregator>().Subscribe(thisType))); 

As long as this code is successfully signed by MainWindowViewModel to receive published messages, the time comes to actually receive messages, nothing happens. If I manually sign all the work 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 say that Windsor will automatically sign if any class inherits IHandle<> ?

In the end, I came to this custom object 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 can see that the subscription was successful, however, if another class posts a message, the MainWindowViewModel class does not receive processing. Manual subscription still works, but I would like to automate this process. I have a feeling that he is not subscribing to the correct instance. I don’t know how to fix it.

I also tried using every other event opened by the Kernel property. Most of them cannot solve the IEventAggregator .

What am I missing?

+7
source share
4 answers

"I have a feeling that he is not subscribing to the correct instance. Of course, how to fix it, though."

You are subscribing to the type of implementation (an instance of System.Type), and not to the actual dependency. Line:

 aggregator.Subscribe(client.Implementation); 

it should be

 aggregator.Subscribe(dependency); 
+3
source

You probably need to configure 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 ensures that all events are aggregated into one basic dictionary (or data type of your choice) instead of the new one created each time IEventAggregator resolves. NTN.

+1
source

Here's how to use IHandler

 public interface IHandle<TClass> : IHandle { void Handle(TClass Subscriber); } 

and here is how to use it.

  public class MyViewModel : IHandle<SubscriberType > { public void Handle(SubscriberType Subscriber) { //Do something here. } } 
0
source

It may be quite late, but this way I was able to achieve this.

 container.AddFacility<StartableFacility>(); container.Register(Component.For<ISubscriber<TagsProcessed>>() .ImplementedBy<TagsProcessedListener>() .OnCreate((kernel, instance) => eventAggregator.Subscribe(instance)).Start()); 
0
source

All Articles