Как вернуть данные из метода с подпиской, используя библиотеки EventAggregator и Microsoft Prism

Я работаю над проектом WPF, используя MVVM и Microsoft Prism libraries. Итак, когда мне нужно общаться через классы, я использую класс Microsoft.Practices.Prism.MefExtensions.Events.MefEventAggregator, публикую события и подписываюсь на методы, как показано ниже:

Чтобы публиковать:

myEventAggregator.GetEvent<MyEvent>().Publish(myParams)

Подписываться:

myEventAggregator.GetEvent<MyEvent>().Subscribe(MySubscribedMethod)

Но мой вопрос: Есть ли способ вернуть некоторые данные из "Subscribed method" после публикации события??


person Dante    schedule 28.06.2012    source источник


Ответы (1)


Насколько я знаю, если все подписчики событий используют параметр ThreadOption.PublisherThread (который также используется по умолчанию), событие выполняется синхронно, и подписчики могут изменять объект EventArgs, поэтому вы могли бы иметь в издателе

myEventAggregator.GetEvent<MyEvent>().Publish(myParams)
if (myParams.MyProperty)
{
   // Do something
}

Код подписчика будет выглядеть так:

// Either of these is fine.
myEventAggregator.GetEvent<MyEvent>().Subscribe(MySubscribedMethod)
myEventAggregator.GetEvent<MyEvent>().Subscribe(MySubscribedMethod, ThreadOption.PublisherThread)

private void MySubscribedMethod(MyEventArgs e)
{
    // Modify event args
    e.MyProperty = true;
}

Если вы знаете, что событие всегда должно вызываться синхронно, вы можете создать свой собственный базовый класс для событий (вместо CompositePresentationEvent<T>), который переопределяет метод Subscribe, и разрешить подписчикам использовать только параметр ThreadOption.PublisherThread. Это будет выглядеть примерно так:

public class SynchronousEvent<TPayload> : CompositePresentationEvent<TPayload>
{
    public override SubscriptionToken Subscribe(Action<TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive, Predicate<TPayload> filter)
    {
        // Don't allow subscribers to use any option other than the PublisherThread option.
        if (threadOption != ThreadOption.PublisherThread)
        {
            throw new InvalidOperationException();
        }

        // Perform the subscription.
        return base.Subscribe(action, threadOption, keepSubscriberReferenceAlive, filter);
    }
}

затем вместо получения MyEvent из CompositePresentationEvent вы получаете его из SynchronousEvent, что гарантирует вам, что событие будет вызываться синхронно и что вы получите измененное EventArgs.

person Adi Lester    schedule 28.06.2012
comment
Спасибо за ваш ответ, я понял вашу точку зрения, я возвращаю данные через EventArgs, и это работает. Просто для протокола: я не смог создать класс SyncronousEvent, так как метод SubscriptionToken не является virtual. Однако ваш вопрос был очень полезен для меня. - person Dante; 29.06.2012
comment
@Dante Вы переопределяете не SubscriptionToken, а метод Subscribe (который является виртуальным). - person Adi Lester; 29.06.2012
comment
Извините, мой плохой, я говорил о методе Subscribe, который не является виртуальным, я смотрю на него прямо сейчас, и если я попытаюсь скомпилировать ваш пример, VS2010 скажет мне, что метод не virtual. В любом случае, ваше решение - это то, что я искал, спасибо - person Dante; 29.06.2012
comment
@Dante Конкретную перегрузку, которую я использовал в своем коде, нельзя было переопределить. Я изменил свой ответ, чтобы использовать правильную перегрузку, которая определенно является виртуальной :) - person Adi Lester; 30.06.2012
comment
Призма 6 изменила CompositePresentationEvent на PubSubEvent stackoverflow.com/q/34668759/2122718 - person marbel82; 02.03.2020