Question

I'm attempting to design an event aggregator for my application. (I am new to the design pattern, so I may not fully understand it yet).

Firstly, I have created a solution already that is somewhat an aggregator but needs improvement and refactoring to achieve better efficiency and lessen dependencies.

1) In the Event Aggregator design pattern, would my .NET data sources be considered the publishers? (I'm uncertain about the publishers' role is).

2) How would I design my solution to handle subscriptions not only to specific data sources, but also specific data events while ignoring others? I would like to see a solution that moves away from keeping lists and looping through them tirelessly.. but not sure if I can avoid this all together.

Was it helpful?

Solution

I think you have to implement a good publisher/subscriber here. My suggestion is something like this:

your publisher: EventAggregator should have methods like:

public void Register(IEventObserver observer, EventFilter filter)
public void Unregister(IEventObserver observer)

your IEventObserver should look like

public interface IEventObserver
{
    void Notify(object eventSource, DetailedEventArgs e);
}

your subscribers should implement this interface.

your EventFilter class should have all the filtering properties that you intend to use. this class can have a method like this:

public bool IsSatisfiedBy(DetailedEventArgs e)

and create a class Named DetailedEventArgs and inherit it from EventArgs, put all the details you want about an event on that.

in the Register method, you should store both filters and observers. now when your EventAggregator catches an event, it should first create the DetailedEventArgs object from the received event, and then loop the observers and their filters to see if the filter is satisfied by the object and if so, call the Notify method of observer with the original sender and DetailedEventArgs object.

I seriously recommend you to check the filter on publisher side and not the subscriber side. because checking in subscriber side will make lots of code duplicate and inconsistency.

EDIT: An example EventFilter and DetailedEventArgs classes:

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
}

hope I helped :)

OTHER TIPS

Check out the MVVM Light Messenger class. I based my implementation on that. However, it uses lists and loops, but I don't see a way around that.

I have seen some complaints about a memory leak, but it has not impacted me, and may be fixed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top