Search code examples
c#structuremapopen-generics

Structuremap returning wrong instance for open generic type?


I am trying to use structuremap with open generic to get instances of a Event handler at run time ,I am using open generic based configuration

     // #1 Configuration
         scan.ConnectImplementationsToTypesClosing(typeof(IHandle<>));
// #2 Actual class
      public class EventHandlerClass : 
            IHandle<MyEvent>,
            IHandle<AnotherEvent>,
            IHandle<ThirdEvent>,
        {
             void IHandle<MyEvent>.Handle(MyEvent args)
            {

            }
             void IHandle<AnotherEvent>.Handle(AnotherEvent args)
            {

            }
             void IHandle<ThirdEvent>.Handle(ThirdEvent args)
            {

            }

        }

My code works for cases where I request the depdendency through constructor injection like this works fine.

public MyClass(IHandle<MyEvent>[] alleventHandlers)
{

}

However in one of my cases , I need to fetch the dependency at runtime . Below is the code I am using

 // Code
 Type t = typeof(IHandle<>);
 MyEvent m = new MyEvent();
 var generic = t.MakeGenericType(m.GetType());
 dynamic instances = nestedContainer.GetAllInstances(genType) as IEnumerable;

 foreach( dynamic inst in instances)
 {
     inst.Handle(m)

 }

I get the following error. {"The best overloaded method match for 'MyNameSpace.EventHandlerClass.Handle(MyNameSpace.Events.ThirdEvent)' has some invalid arguments"}

GetAllInstances somehow seems to return a object of EventHandlerClass with a Handle method expecting ThirdEvent event though I called GetAllInstances with the correct type.

Is this a bug ? or have i made a mistake in the configuration ?


Solution

  • The dynamic variable only has access to type methods (typically public, but is based on context). It does not have access to interface methods that are explicitly implemented. The only way to invoke explicit interface implementations is to cast the object to the interface.

    So you have two options, either a) implement the interfaces implicitly as suggested by @Yacoub, or b) use reflection to invoke the method.

    foreach(dynamic inst in instances)
    {
         Type type = inst.GetType();
         Type interfaceType = type.GetInterfaces().Single(t => t == generic);
         interfaceType.GetMethod("Handle").Invoke(inst, new object[] { m });
    }