Использование Windsor для автоматической подписки на агрегатор событий с пользовательским средством - PullRequest
7 голосов
/ 12 августа 2011

Чтение в этом блоге упоминается, что вы можете заставить свой 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<>?

Я закончил тем, что придумал это пользовательское средство, которое подписывается.

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

Глядя на класс EventAggregator, предоставленный Caliburn.Micro Я могу видеть, что подписка прошла успешно, однакоесли другой класс публикует сообщение, класс MainWindowViewModel не обрабатывается.Вручную подписка все еще работает, но я хотел бы автоматизировать этот процесс.У меня такое ощущение, что это не подписка на правильный экземпляр.Не уверен, как это исправить.

Я также пытался использовать любое другое событие, предоставляемое свойством Kernel.Большинство из них не могут решить IEventAggregator.

Чего мне не хватает?

Ответы [ 4 ]

3 голосов
/ 17 августа 2011

"У меня такое ощущение, что он не подписывается на правильный экземпляр. Однако я не уверен, как это исправить."

Вы подписываетесь на тип реализации (экземплярSystem.Type), а не фактическая разрешаемая зависимость.Строка:

aggregator.Subscribe(client.Implementation);

должна быть

aggregator.Subscribe(dependency);
1 голос
/ 17 августа 2011

Возможно, вам нужно настроить IEventAggregator как одиночный. Не уверен, как именно это будет сделано с Windsor, но с ninject вы сделаете что-то вроде

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

Наличие синглтона гарантирует, что все события будут объединены в один базовый словарь (или тип данных по вашему выбору), вместо того, чтобы создавать новый каждый раз, когда вы разрешаете IEventAggregator. НТН.

0 голосов
/ 25 июля 2014

Это может быть довольно поздно, но вот как я смог добиться этого

container.AddFacility<StartableFacility>();

container.Register(Component.For<ISubscriber<TagsProcessed>>()
                                    .ImplementedBy<TagsProcessedListener>()
                                    .OnCreate((kernel, instance) => eventAggregator.Subscribe(instance)).Start());
0 голосов
/ 12 августа 2011

как это сделать IHandler

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

и вот как это использовать ..

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