EventAggregator and Handlers

Topics: Bugs
Jan 10, 2013 at 10:01 PM

Hey All,

I have a question regarding the behavior of the EventAggregator implementation and how Handlers are intended to work with it.  Specifically I'm using the EventAggregator package from NuGet.

I have read a couple articles talking about the polymorphism supported with the EventAggregator.  (http://devlicio.us/blogs/rob_eisenberg/archive/2011/05/30/caliburn-micro-soup-to-nuts-part-8-the-eventaggregator.aspx

Correct me if I'm wrong.  The sample on here leads me to believe if I create a handler that handles multiple types of objects and those objects are related through inheritance, that I will receive a Handle message for each object type in the inheritance chain.  This doesn't appear to be the case because of the way the Handler class is implemented.  The loop that is looping through the supported handlers prematurely exits when it finds a Handler to call.  Is this intended or a bug of a misplaced "return true" statement?  Removal of this statement appears to perform the advertised multi-cast-like behavior.

 

protected class Handler {
            readonly WeakReference reference;
            readonly Dictionary supportedHandlers = new Dictionary();

            public Handler(object handler) {
                reference = new WeakReference(handler);

                var interfaces = handler.GetType().GetInterfaces()
                    .Where(x => typeof(IHandle).IsAssignableFrom(x) && x.IsGenericType);

                foreach(var @interface in interfaces) {
                    var type = @interface.GetGenericArguments()[0];
                    var method = @interface.GetMethod("Handle");
                    supportedHandlers[type] = method;
                }
            }

            public bool Matches(object instance) {
                return reference.Target == instance;
            }

            public bool Handle(Type messageType, object message) {
                var target = reference.Target;
                if (target == null) {
                    return false;
                }

                foreach(var pair in supportedHandlers) {
                    if(pair.Key.IsAssignableFrom(messageType)) {
                        var result = pair.Value.Invoke(target, new[] { message });
                        if (result != null) {
                            HandlerResultProcessing(target, result);
                        }
                        return true;
                    }
                }
                
                return true;
            }
        }

 

 

Feb 11, 2013 at 4:52 PM
I came here for the exact same issue. Surprised to not see a response in the month since you posted. I also don't see an issue posted in the tracker so I am going to create one hoping to get some feedback. I will link to this discussion.
Feb 19, 2013 at 5:40 PM
Edited Feb 19, 2013 at 5:40 PM
dfmartin1972 wrote:
I came here for the exact same issue. Surprised to not see a response in the month since you posted. I also don't see an issue posted in the tracker so I am going to create one hoping to get some feedback. I will link to this discussion.
Yep, nothing at all. Well if you are still inclined to use this library you can make the modification I stated above and comment out that line of code. Seems hackish to have to do such a thing. If you are just after the Event Aggregator portion, I guess I would recommend switching to another library or even rolling your own. There are some nice examples online on using Reactive Extensions to accomplish the pattern with very little code.
Coordinator
Feb 19, 2013 at 8:31 PM
Sorry we missed this guys! I think it's a bug. We will investigate.
Feb 21, 2013 at 8:34 AM
Edited Feb 21, 2013 at 8:34 AM
I wrote my own EventAggregator beacuse I needed it abstracted from the GUI to be used from backend,

My implementation uses contra-variants and a pretty straight forward implementation of subscription, works well with polymorphism
    public void Publish<T>(T message) where T : class
    {
        subscribers
            .OfType<IHandle<T>>()
            .ForEach(s => s.Handle(message));
    }
Check it out
https://github.com/AndersMalmgren/FreePIE/tree/master/FreePIE.Core/Common/Events