使用Windsor自动订阅带有自定义功能的事件聚合器

本文关键字:功能 事件 自定义 Windsor 使用 | 更新日期: 2023-09-27 18:05:29

阅读这篇博客文章,它提到您可以让您的DI容器自动订阅事件,如果它实现了IHandle<>。这正是我想要完成的。

这是我到目前为止写的。

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

当此代码成功订阅MainWindowViewModel以接收已发布的消息时,实际接收消息时什么也没有发生。如果我手动订阅,所有工作如预期。

这是我的MainWindowViewModel班。

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);
    }
}

如果任何类继承了IHandle<>,如何让Windsor自动订阅

我最终想出了这个订阅的自定义工具。

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);
        }
    }
}

查看Caliburn提供的EventAggregator类。Micro - I可以看到订阅是成功的,但是如果另一个类发布消息,MainWindowViewModel类没有得到处理。手动订阅仍然有效,但我想自动化这个过程。我感觉它的下标不是正确的实例。但我不知道如何解决这个问题。

我还尝试使用Kernel属性暴露的所有其他事件。大多数不能解析IEventAggregator

我错过了什么?

使用Windsor自动订阅带有自定义功能的事件聚合器

"我感觉它没有订阅正确的实例。不不过,我知道如何解决这个问题。"

您订阅的是实现的类型(System.Type的实例),而不是正在解析的实际依赖项。线:

aggregator.Subscribe(client.Implementation);
应该

aggregator.Subscribe(dependency);

您可能需要将您的IEventAggregator配置为单例。我不确定温莎会怎么做,但是用ninject你会这样做

Bind<IEventAggregator>().To<ConcreteEventAggregator>().InSingletonScope()

拥有一个单例将确保所有事件被聚合到一个单一的底层字典(或您选择的数据类型),而不是每次解析IEventAggregator时都创建一个新的字典。HTH .

这是如何实现IHandler

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

,这是如何使用它…

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

这可能有点晚了,但这就是我如何做到的

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