使用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
。
我错过了什么?
"我感觉它没有订阅正确的实例。不不过,我知道如何解决这个问题。"
您订阅的是实现的类型(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());