Prism — EventAggregator.GetEvent‹›.Subscribe() — Использование обобщений и ограничений

У меня проблема с подпиской на события с агрегатором событий, который входит в состав prism framework.

Если я использую что-то вроде

eventAggregator.GetEvent<string>().Subscribe(MyMethod)

тогда все работает нормально, мой метод срабатывает, когда событие опубликовано.

Однако при переходе к более сложному объекту, отличному от строки, я сталкиваюсь с проблемами.

У меня есть куча классов, которые, например, происходят из интерфейса (IRequest).

У меня есть настройка класса событий следующим образом

public class MyEvent<TRequest> : PubSubEvent<MyClass<TRequest>> where TRequest : IRequest {}

У меня есть общий класс (MyClass), который использует внутри него объект IRequest - опять же, на данный момент все работает нормально.

Теперь предположим, что я публикую событие MyClass, которое использует профиль объекта внутри него:

eventAggregator.GetEvent<MyEvent<Profile>>().Publish(myProfileObject);

В моей подписке мне нужен метод, который может перехватывать все события MyEvent. Независимо от того, является ли T профилем или каким-либо другим объектом, производным от IRequest, здесь у меня, похоже, возникают проблемы.

В следующих примерах первый работает, а второй нет — в идеале я хотел бы использовать что-то похожее на второй.

eventAggregator.GetEvent<MyEvent<Profile>>().Subscribe(test1);
void test1 (MyClass<Profile> obj)
{
  //Some stuff here
}

eventAggregator.GetEvent<MyEvent<IRequest>>().Subscribe(test2);
void test2<T>(MyClass<T> obj) where T : IRequest
{
  //never gets called
}

Я предполагаю, что, поскольку Profile происходит от IRequest, он должен работать??? Но это не так!!

Любая помощь будет оценена по достоинству.

ОБНОВЛЕНИЕ
Если я использую следующее, это работает, но мне потребуется создать отдельную подписку для каждого доступного типа IRequest — я хочу иметь только одну подписку.

eventAggregator.GetEvent<MyEvent<Profile>>().Subscribe(test2);
eventAggregator.GetEvent<MyEvent<User>>().Subscribe(test2);

person David Hamilton    schedule 08.10.2015    source источник
comment
Привет. Я думаю, что ваш вопрос показывает усилия, но вы могли бы мотивировать ленивых людей, таких как я, подготовив образец полной копии урезанного образца + использованные ссылки nuget. Иногда при подготовке такого вы также найдете источник, почему он не работает (по крайней мере, я уже делал пару раз)   -  person Dbl    schedule 08.10.2015
comment
@AndreasMüller - Спасибо, постараюсь добавить дополнительные ссылки/ссылки и т. д. в будущем - хотя в этом случае код, который я использую, намного сложнее, поэтому я пытался предоставить соответствующую информацию, упростив все это.   -  person David Hamilton    schedule 09.10.2015


Ответы (1)


MyEvent<IRequest> и MyEvent<Profile> не совпадают, поэтому EventAggregator не считает это одним и тем же событием. Чтобы разрешить ковариантные типы, вы можете исправить это с помощью модификатора out в C# 4. Что-то вроде этого должно работать:

public interface IMyClass<out T> where T : IRequest { }

public class MyClass<T> : IMyClass<T> where T : IRequest { }

public class MyEvent<TValue> : PubSubEvent<IMyClass<TValue>> where TValue : IRequest { }

Тогда ваш агрегатор событий будет выглядеть примерно так:

 _eventAggregator.GetEvent<MyEvent<IRequest>>().Subscribe(Received);

 private void Received(IMyClass<IRequest> obj)
 {

 }

_eventAggregator.GetEvent<MyEvent<IRequest>>().Publish(new MyClass<Profile>());

Это помогает?

person Community    schedule 08.10.2015