Search code examples
c#dependency-injectioninversion-of-controlunity-containersimple-injector

Register generic types with constructor in SimpleInjector how?


I use Microsoft Unity as IoC container and wrote some code like this:

public static void RegisterTypes(IUnityContainer container)
{
    MyContext ctx = new MyContext (); // is EntityFramework DbContext
    container.RegisterType(typeof(IEntityRepository<>),
                           typeof(EntityRepository<>), 
                           new InjectionConstructor(ctx));
    container.RegisterType(typeof(IEntityService<>), 
                           typeof(EntityService<>));
}

It works for me without problem, but I want to know how to write its equivalent in SimpleInjector.


Solution

  • There's nothing special about your configuration and @Patryk pointed you at the correct documentation here. Simple Injector will do the auto-wiring for you, so you don't have to specify constructor arguments explicitly.

    But there's something smelly about your current setup, because it seems like your DbContext is a singleton; you only have one instance for the duration of your whole application. This is in almost all cases a very bad idea. Either your application lives for a long time (such as a Windows Service) or handles many threads concurrently (such as ASP.NET and WCF). Only in the case where you have a single-threaded application that lives for a very short time (such as a console application), you might have just one DbContext. You don't want to register your DbContext as a singleton.

    But perhaps it is not a singleton and you actually call this RegisterTypes once per request. In this case you will have one DbContext per request, but this means you create a new container instance each request and that will be bad as well. That will be very bad for performance with both Unity and Simple Injector. DI libraries are especially optimized for having one single container instance for the duration of the application.

    So you rather want to have one single container instance for the duration of your application and have your DbContext usually registered with a Scoped lifestyle.

    In Simple Injector there are many scoped lifestyles, each one is specific for the chosen technology. Assuming you are using MVC, your registration might look like this:

    public static void RegisterTypes(Container container)
    {
        container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
    
        container.Register<MyContex>(Lifestyle.Scoped);
    
        container.Register(typeof(IEntityRepository<>), typeof(EntityRepository<>));
    
        container.Register(typeof(IEntityService<>), typeof(EntityService<>));
    }
    

    Do note the registration for EntityRepository<T>. If EntityRepository<T> has a constructor argument of MyContext, and MyContext is registered in the container, Simple Injector will be able to inject this dependency for you in its constructor. This process is called auto-wiring and you should normally let the container do this for you, because this makes your DI configuration much more maintainable.