Search code examples
c#dependency-injectioninversion-of-controlrebuslight-inject

Using LightInject to register all classes that implement a generic interface


I can't figure out how to use LightInject's API to register all handlers defined in a given class. In this case, defining handlers for Rebus using the LightInject adapter.

So given a handler defined as:

public class MyHandler : IHandleMessages<MyMessage>
{
}

I thought I could register all in the assembly as follows:

container.RegisterAssembly(typeof(HandlerBase).Assembly,
    (s, Type) => Type.GetInterfaces().Contains(typeof(IHandleMessages<>)));

but when I try to get instances registered of that type they are not found (container.AvailableServices shows the type but the value property is null)

var detectedHandlers = container.GetAllInstances<IHandleMessages<MyMessage>>();

What does work, is manually defining it as follows:

container.Register<IHandleMessages<MyMessage>, MyHandler>();

but that's not ideal as it requires manual registration. Is there a way to do it with LightInject?


Solution

  • Your registration will not work, because non-generic types, such as MyHandler do never implement an open-generic abstraction, such as IHandleMessages<>. Instead, you should check to see if MyHandler implements a closed version of IHandleMessages<>:

    container.RegisterAssembly(typeof(HandlerBase).Assembly,
       (s, _) => s.IsGenericType && s.GetGenericTypeDefinition() == typeof(IHandleMessages<>));
    

    Note that the previous registration simplifies the registration further by using the s service type argument, which saves you from having to call .GetInterfaces().