Do I need to register concrete root types in Simple Injector?

Viewed 339

Reading the Simple injector docs to get a handle on how it all works and I read the below paragraph. I understand what its explaining apart from the part in bold. What does it mean?

The technique for keeping this dependency to a minimum can be achieved by designing the types in your application around the constructor injection pattern: Define all dependencies of a class in the single public constructor of that type; do this for all service types that need to be resolved and resolve only the top most types in the application directly (i.e. let the container build up the complete graph of dependent objects for you)

Ignoring my lack of understanding regarding the sentence above I ploughed on but when trying to set up Simple injector for Web api came across this line of code container.RegisterWebApiControllers(GlobalConfiguration.Configuration); With this explanation

Because controllers are concrete classes, the container will be able to create them without any registration.

Does this mean if I have a bunch of classes that don't rely on an interface, I can create them using a single line of code? (if so how, should I).

2 Answers

What this means is a good practice of not relying on the DI-container in your code apart from some top-level where you have to do that to "kick-start" the application.

That will mean that all your classes will just have constructor dependencies in the form of interfaces and will not do Container.Resolve. This will only be called on the top level of you application.

In some frameworks you won't even have to do that yourself because it's a part of how framework operates. As far as I remember in .Net core e.g. you won't need to do a resolve, but it will happen inside framework when the controllers will be initiated.

Because controllers are concrete classes, the container will be able to create them without any registration.

This means you won't have to register the controllers themselves in the container. Container will only resolve controller dependencies themselves, create controllers and pass all of the resolved dependencies in them.

P.S. Resolving only in the root of you application is nothing specific for the SimpleInjector. It is a good practice that can be applied to any container and SimpleInjector can be used even if you don't follow it, which probably no one these days would recommend.

do this for all service types that need to be resolved and resolve only the top most types in the application directly

What this means is that, once you solely use Constructor Injection as a way for a class to get a hold of its dependencies, you will end up building object graphs that are potentially many layers deep. Take this object graph for instance:

new HomeController(
    new ProductService(
        new SqlProductRepository(
            new CommerceContext(connectionString)),
        new AspNetUserContextAdapter(
            httpContextAccessor)));

PRO TIP: Did you know that you can let Simple Injector visualize your object graphs for you inside the debugger? This is explained here.

Here you see that HomeController has one dependency (IProductService) that it gets through its constructor. ProductService itself has two dependencies (IProductRepository and IUserContext) that are as well supplied through its constructor. This can go many layers deep.

Having Constructor Injection as the sole means to supply dependencies to a class means that the class is not allows to request them itself by calling back into the Container. This is a well-established anti-pattern called Service Locator. Constructor Injection simplifies your classes and allows the Container to analyze the object graph for you and detect any anomalies.

and resolve only the top most types in the application directly

When the whole object graph is constructed using Constructor Injection, it means that you only have to ask for a HomeController, which is the top most type in the graph. Nothing depends on HomeController; HomeController depends on everything (implicitly). All application behavior is invoked through these top most types. In an MVC application these typically are controllers, HTTP handlers and modules.

Because controllers are concrete classes, the container will be able to create them without any registration.

This statement is a bit misleading. Yes, it is true that Simple Injector will be able to create a requested concrete type for you, even if that type isn't registered. As explained here in the documentation however, it is best to always register your root types in the container. This ensures that the container knows about those types and it allows analysis and verification on those types as well. Not registering those concrete root types will give you a false sense of security when you call container.Verify(). Verify is only able to verify on the registrations that it knows of. When an unregistered concrete type is referenced as a dependency, the container still knows about it, but that obviously doesn't hold for root types, since nothing depends on them.

WARNING: In Simple Injector v5, this behavior is likely going to change. By default, Simple Injector v5 will probably not allow concrete unregistered root types to be resolved. see

Related