Search code examples
c#inversion-of-controlioc-containersimple-injector

SimpleInjector duplicate registrations for RegisterManyForOpenGeneric for implementations with more than one interface


I have an issue regarding automatic registration of IEventHandler<> with RegisterManyForOpenGeneric which results in duplicate registrations (something I am doing wrong I am sure).

In my application an event is raised by an external input which is then dispatched to all classes which implement the IEventHandler<> of the incoming event type:

// during bootstrap, the below code is called
resolver.RegisterManyForOpenGeneric(typeof(IEventHandler<>), AppDomain.CurrentDomain.GetAssemblies());

// when the app is running, an external event is published below:
public void PublishEvent(object evnt)
{
    var handlerType = (typeof(IEventHandler<>)).MakeGenericType(evnt.getType());
    var handlers = resolver.GetAllInstances(handlerType).ToList();

    foreach(var handler in handlers)
    {
        /* do some reflection to get method */
        method.Invoke(handler, new[] { evnt } });
    }
}

// the below is an event handlers that get automatically wired up OK
class TopicVoteStatisticsProjection : IEventHandler<AdminActedOnTopic>
{
    public void Handle(AdminActedOnTopic evnt)
    {
        // for every event, this gets called once and all is good
    }    
}

With the above all the IEventHandler<> classes are wired up automatically, and all events published via the above code are sent to the handlers OK (for the above scenario where I have the single interface IEventHandler<AdminActedOnTopic>).

If however I register more than one event handler interface within the same implementation class:

class TopicVoteStatisticsProjection : IEventHandler<UserVotedOnTopic>, IEventHandler<AdminActedOnTopic>
{
    public void Handle(UserVotedOnTopic evnt)
    {
    }

    public void Handle(AdminActedOnTopic evnt)
    {
        // for every event, this gets called twice!!
    }
}

Then what happens is is the same handler for IEventHandler is returned twice as:

handlers = resolver.GetAllInstances(typeof(IEventHandler<AdminActedOnTopic>)).ToList();

/* above query returns the following instances: 
Projections.TopicVoteStatistics.TopicVoteStatisticsProjection
Projections.TopicVoteStatistics.TopicVoteStatisticsProjection
*/

This is bad as it doubles up on my calculations! In this case the two events are related and I would ideally like to keep them together in the same handler implementation.

My question is please - How can I have automatic registration of handlers, some of which that implement more than one IEventHandler<> interface, without the duplicate registrations?


Solution

  • I think that the behaviour you are seeing is a bug which was introduced in version 2.7. It is described in detail here: https://simpleinjector.codeplex.com/workitem/20996

    It should be fixed from version 2.7.2.