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

时间:2011-08-12 13:12:49

标签: c# castle-windsor caliburn.micro

阅读this博客文章,它提到您可以让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.Micro提供的EventAggregator类我可以看到订阅成功,但是如果另一个类发布消息,MainWindowViewModel类没有得到处理。手动订阅仍然有效,但我想自动化这个过程。我有一种感觉,它没有订阅正确的实例。但不知道如何解决这个问题。

我还尝试使用Kernel属性公开的所有其他事件。他们中的大多数都无法解决IEventAggregator

我错过了什么?

4 个答案:

答案 0 :(得分:3)

  

“我觉得它没有订阅正确的实例。不是   确定如何解决这个问题。“

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

aggregator.Subscribe(client.Implementation);

应该是

aggregator.Subscribe(dependency);

答案 1 :(得分:1)

您可能需要将IEventAggregator配置为单例。不知道究竟如何使用Windsor,但是使用ninject你会做类似

的事情
Bind<IEventAggregator>().To<ConcreteEventAggregator>().InSingletonScope()

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

答案 2 :(得分:0)

这是如何实现Handler

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

这是如何使用它..

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

答案 3 :(得分:0)

这可能已经很晚了,但这就是我能够实现它的方式

container.AddFacility<StartableFacility>();

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