This project is read-only.

What is your advice regarding dependencies to the DI container with packages?

Oct 14, 2013 at 10:36 PM
This question was asked by blueling on this thread.

What is your advice regarding dependencies to the DI container with packages? Is it best to create "micro-assemblies" which only contain the container-registration part for a module to avoid any assembly dependency to Simple Injector in the modules?
Oct 14, 2013 at 10:36 PM
Edited Dec 19, 2013 at 5:20 PM
> And regarding packages: What is your advice regarding dependencies to the DI container with packages?

To be honest, I would say that a 'modules' or 'packages' feature is in most cases pretty useless. It's even just easier to have a public static Initialize(Container container) method in your Business Layer (or whatever layer you want) that container the registration logic for that layer and the Composition Root in the startup project can simply call that Initialize method and pass in a Container instance. There's generally no advantage in doing this by creating an IPackage implementation (or whatever interface your DI container supplies you with).

The only scenario I can think of where this is useful is when you don't know up front which assemblies you load in your application. In that case each assembly can contain some bootstrapping code and you can dynamically look for IPackage implementations. But this will hardly ever work in practice, since the registration process will often break (either explicitly or silently, depending on the container and whether you verify on startup), since dynamically loaded assemblies can easily register types in incompatible ways.

This wont happen if each assembly has its own isolated object graph, but in that case there's no need to let that assembly make its registrations in the main container; it can have its own composition root and its own container instance.

So my advice is to not use them, unless you have no idea which assemblies are loaded at runtime, and those assemblies need to register types in the application's container.

> Is it best to create "micro-assemblies" which only contain the container-registration part for a module to
> avoid any assembly dependency to Simple Injector in the modules?

Unless you have multiple applications that share the same source code (for instance both a MVC app and WCF service on top of a shared business layer), you should register all your dependencies in one place in the startup project. If you have multiple applications, you will have to move duplicate registrations to a shared assembly. This can be placed inside your BL or have a seperate BL.Bootstrap assembly on top of your BL (if you want to keep your BL assembly clean from referencing the DI framework). Prevent from having registration logic in each assembly, unless your applications use a mix of those assemblies. Usually you'll have both a MVC and WCF application with their own code and they share the BL and everything below. So both will use the same BL, DAL, Domain, etc. No need to have code for each assembly. Place all registrations for BL, DAL and Domain inside the BL or in the BL.Bootstrapper. More info in this stackoverflow thread.
Marked as answer by dot_NET_Junkie on 3/2/2014 at 11:17 AM
Dec 19, 2013 at 1:38 PM
I am starting a project that will be sharing the same source code between an MVC app and a console app, for batch processing. So, I started to put the duplicate registrations into a shared assembly.

My problem is that I'm pretty much creating a facade to Simple Injector and my facade its really just copying the same method signatures which I need to call to register and resolve types in my MVC app and Batch Processing App. I have to do this because in the composition root of each separate application I need to register specific parts like in MVC i need to register all the controllers and hook that up to the controller factory and same with the Filters to do the property injection.

Something just doesn't feel right about it because the facade in my shared library that uses Simple Injector is starting to look like Simple Injector. I mean.. I have at least a dozen methods that have the exact same method signature as Simple Injector which just pass the same parameters through to Simple Injector.

Am I doing this right?
Dec 19, 2013 at 2:32 PM
I would say that what you're doing is indeed suboptimal. I would say that creating a facade around the container is useless, because there are still only three places in your solution that know about a container. You can simply refer to Simple Injector in those three places.

What I imagine is that your shared bootstrapper library looks like this:
using SimpleInjector;

public static class Bootstrapper
{
    public static void Initialize(Container container)
    {
         // TODO: Place all shared registrations here.
    }
}
The composition roots of both the MVC app and the console app can simply call the shared Bootstrapper.Initialize method and prepend and append their own registrations:
protected void Application_Start(object sender, EventArgs e)
{
    // Create the container as usual.
    var container = new Container();

    // Register your types, for instance:
    Bootstrapper.Initialize(container);

    // add a MVC specific decorator here
    container.RegisterDecorator(typeof(ICommandHandler<>),
        typeof(GlimpseForMvcLoggingCommandHandlerDecorator<>);

    // This is an extension method from the integration package.
    container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
    
    // This is an extension method from the integration package as well.
    container.RegisterMvcAttributeFilterProvider();

    container.Verify();
    
    DependencyResolver.SetResolver(
        new SimpleInjectorDependencyResolver(container));
}
In the example, an extra decorator is registered. In most cases, the order in which you make your registrations does not matter, so you could also register your MVC controllers before calling Bootstrapper.Initialize. The exception to this rule are the decorators, since multiple decorators can be applied and they are wrapped in the order in which they are registered. The decorator in this example will be wrapped around all other decorators that already have been registered in the Bootstrapper.Initialize. If you want this decorator to be wrapped directly around the real class, and all other decorators after that, you'll have to move that registration before the call to Bootstrapper.Initialize.
Dec 20, 2013 at 1:29 PM
Edited Dec 20, 2013 at 2:03 PM
Never really thought to do it like that but it makes perfect sense. Thank you!

The reason I didn't do it like this before though was because I didn't want to create a dependency on Simple Injector.

Using this method, in my unit test projects I will also have to add a reference to Simple Injector.

But, I guess since Simple Injector is only used in the composition root and is not scattered throughout the rest of the code. Re-factoring should be easy if I ever needed to replace/update it.
Dec 20, 2013 at 2:51 PM
Exactly, Simple Injector is only used in your composition root. Since you need to minimize the code duplication, part of your composition root is shared and this (of courser) needs access to Simple Injector. As long as you keep the rest of the application free from any dependencies to Simple Injector (or any DI container in general) you'll be fine. Your unit tests should typically be free from using any DI container (both directly and indirectly). Your tests (or your mocking framework) should call the constructor of a class under test; not your DI container.

The only exception to this are the (integration) tests that check the validity and health of your container. I usually write a few integration tests that request an initialized container from the bootstrapper and call verify on it. Another test checks whether there are any diagnostic warnings.
Dec 20, 2013 at 3:23 PM
Edited Dec 20, 2013 at 3:23 PM
Great, thank you very much. It's very reassuring to get confirmation on how to do this from an authoritative voice.
Dec 20, 2013 at 4:49 PM
You're more than welcome.