Event Aggregator: нужна помощь в изменении решения
Я пытаюсь разработать агрегатор событий для своего приложения. (Я новичок в шаблоне проектирования, поэтому я еще не до конца его понимаю).
Во-первых, я уже создал решение, которое в некоторой степени является агрегатором, но нуждается в улучшении и рефакторинге для достижения большей эффективности и уменьшения зависимостей.
1) В шаблоне разработки Event Aggregator мои источники данных.NET будут считаться издателями? (Я не уверен насчет роли издателей).
2) Как бы я разработал свое решение для обработки подписок не только на конкретные источники данных, но и на конкретные события данных, игнорируя при этом другие? Я хотел бы увидеть решение, которое отошло бы от ведения списков и неустанного их просмотра... но не уверен, смогу ли я избежать всего этого вместе.
2 ответа
Я думаю, что вы должны реализовать хорошего издателя / подписчика здесь. Мое предложение примерно так:
ваш издатель: EventAggregator
должны иметь такие методы, как:
public void Register(IEventObserver observer, EventFilter filter)
public void Unregister(IEventObserver observer)
ваш IEventObserver
должен выглядеть так
public interface IEventObserver
{
void Notify(object eventSource, DetailedEventArgs e);
}
Ваши подписчики должны реализовать этот интерфейс.
ваш EventFilter
Класс должен иметь все фильтрующие свойства, которые вы намереваетесь использовать. этот класс может иметь такой метод:
public bool IsSatisfiedBy(DetailedEventArgs e)
и создать класс Named DetailedEventArgs
и унаследовать это от EventArgs
, поместите все детали, которые вы хотите о событии на этом.
в Register
Метод, вы должны хранить как фильтры, так и наблюдатели. теперь, когда ваш EventAggregator
ловит событие, оно должно сначала создать DetailedEventArgs
объект из полученного события, а затем зациклить наблюдателей и их фильтры, чтобы увидеть, удовлетворен ли фильтр объектом, и если это так, вызвать метод Notify наблюдателя с исходным отправителем и DetailedEventArgs
объект.
Я настоятельно рекомендую вам проверить фильтр на стороне издателя, а не на стороне подписчика. потому что проверка на стороне подписчика сделает много кода дублирующимся и непоследовательным.
РЕДАКТИРОВАТЬ: пример EventFilter
а также DetailedEventArgs
классы:
public class EventFilter
{
private List<Type> SourceTypes;
private List<EventType> EventTypes;
public EventFilter() : this(new Type[] { }, new EventType[] { }) { }
public EventFilter(IEnumerable<Type> sourceTypes, IEnumerable<EventType> eventTypes)
{
SourceTypes = new List<Type>(sourceTypes);
EventTypes = new List<EventType>(eventTypes);
}
public void AddSourceType(Type type)
{
AddItemToList(SourceTypes, type);
}
public void AddEventType(EventType type)
{
AddItemToList(EventTypes, type);
}
private void AddItemToList<T>(List<T> list, T item)
{
lock (list)
{
if (!list.Contains(item))
list.Add(item);
}
}
public bool IsSatisfiedBy(DetailedEventArgs args)
{
return SourceTypes.Contains(args.Source.GetType()) && EventTypes.Contains(args.EventType);
}
}
public class DetailedEventArgs : EventArgs
{
public EventArgs SourceArgs { get; private set; }
public object Source { get; private set; }
public EventType EventType { get; private set; }
public DetailedEventArgs(object source, EventArgs sourceArgs, EventType eventType)
{
Source = source;
SourceArgs = sourceArgs;
EventType = eventType;
}
}
public enum EventType
{
EventType1,
EventType2,
EventType3
}
надеюсь я помог:)
Проверьте класс MVVM Light Messenger. Я основал свою реализацию на этом. Тем не менее, он использует списки и циклы, но я не вижу способа обойти это.
Я видел некоторые жалобы на утечку памяти, но это не повлияло на меня и может быть исправлено.