Get injected into the world of inverted dependencies

Introduction

You have probably heard of inversion of control containers (or IoC containers as they are refered to) by now. If you have not you should probably lock the door and continue to read this article really slowly to understand all the goodies. This article aims to reveal the secrets, and to introduce you to the new world where injected dependencies will make your applications more mean and lean.

But before we begin we have to understand the problem that IoC containers solves for us. But it all began with dependency injection, or as Mr SOLID says: "Let's invert those dependencies". Look at the following simple example:

There you have it. We have moved the dependency management from the class itself to the calling code. By doing so we promote code reuse since we can now control how the car is built and which parts that it should use. The CEOs in the vehicle industry would hold their heads screaming and crying at the same time if it were that easy for them. So dear fellow programmer: Take advantage of that power.

Now you are probably asking yourself, "Why the shell do I need an IoC container for that? I can just create those dependencies by myself." True. Absolutely correct. I should probably go to bed right now ...

Let's take another example. We have a fairly large application which uses the repository pattern. And we have used a database within our repositories as a data source. Since we use dependency inversion without a container we have the following code:

We have to go through every 20 or so controllers to switch implementation. And since we code against classes, and not abstractions as dependency inversion principle says, we have to replace the implementations with new ones too. Thus destroying binary compability (which means that we can't switch the DLL for another one, we have to recompile the entire application).

With an IoC (and dependencies against abstrations) we would instead have written:

We have to repeat that code bloat in every place where we want to use the TodoService. We could of course use the Abstract factory pattern, the Builder pattern or Singleton pattern. All of those would work for different parts of the problem, but the solutions would be a more complex than just telling the container which classes we have.

With our container we'll just map each class to the service(s) that it implements:

container.RegisterType<IUserRepository,UserRepository>();
container.RegisterType<IMessageRepository, MessageRepository>();
//google "lambda expresions" if you don't understand the line below
container.RegisterFactory<IDomainEventDispatcher>(container => new DomainEventDispatcher(container));
container.RegisterType<IEntityValidator, EntityValidator>();
container.RegisterType<ITodoService, TodoService>();
// user the service location pattern to get the service
var service = container.Resolve<ITodoService>();

See the difference? We don't have to know which depenencies each class have. We only have to know which classes we have created. That means that we never have to do anything when a class changes it's dependencies (other than adding a new class to the container).

So let's see how we look at dependencies when we are using an IoC container:

We know that the class has dependencies, but we really do not care since the class is created for us. We have gone from having to know all dependencies and how they should be created to only knowing which service we want to use.

Wierd words

There are some terms that you need to know when speaking IoCly with someone, and these are:

Term

Description

Service

The thing which is requested from the container. Typically an interface like IUserRepository, but can also be a class

Concrete

The object which is returned when a service is requested. Would be the DbUserRepository object if a IUserRepository is requested

Transient

A new object will be returned each time a service is requested from the container

Scope

A subset of a container which contains objects with a limited lifetime. The objects are disposed when the scope is closed.

Child container

The most typical implementation of a scope. (A container which only stores scoped objects and uses the parent container for everything else)

Lifetimes

So you have seen that the container can help you assemble/create all your objects for you. You just tell it which service that you want to get and you'll get the proper concrete(s). It's great, isn't it? However, that's just half of what the container can do for you.

You have probably heard of the singleton pattern and that it prevent you from using one of the fundamental principles of object oriented programming: Extension through inheritance. You can of course combine the singleton pattern with the proxy pattern, which would take you a bit further.

With a container you do not have that limitation. The container do not just handle the dependencies, or do also control the lifetime of each object. It does that since it holds a reference to each created object and only removes that reference (and disposes all classes which implement IDisposable) upon certain conditions.

The typical usage of a container is that you generate it when your application starts and dispose it when your application ends. That enables you to be able to provide to kind of lifetimes for all of your objects: Singletons and transient.

That's quite interesting, since you do not have to do anything special in your classes to make them singletons (other than making sure that they are thread-safe and/or manage their state fields correctly). In other words: Extension through inheritance is still possible. You just create a new concrete and register the new implementation instead.

Scoping

We introduced a new thing in the previous section. And that was a class with a limited lifetime. The nhibernate session (could have been an ADO.NET connection, a TCP connection or something similar). Those classes stop working when the connection is lost, and continue to fail on all following calls.

We also have classes which are not thread safe.

The obvious approach to those two problems is to handle them internally in the classes. That will unfortunally increase the complexity in those classes. And with complexity comes bugs.

There is, however, another solution: Scoped objects.

Inversion of control containers can create scopes, which really means that the objects have a limited lifetime and are stored in a thread specific storage (which makes the objects thread safe). A typical scope is the one of a HTTP Request/Response cycle.

Introducing the container

So let's start playing with a container then. I've been around the world and back. I've sailed the seven seas. All of that just to be able to give you the perfect IoC container. Believe it or not, IFOUND IT! It's called Griffin.Container and is made by me .

Register those classes

I showed you in the previous section the traditional approach used to register classes in a container. That is to use RegisterType and similar methods. But that's inefficient and time consuming. I've created an alternative and more conventional way of registering types.

What you do is decorate each class which should be registered in the container with an attribute named [Component].

The first parameter to RegisterComponents tells the container that all classes which uses just [Component] (without a lifetime specified) should be registered as scoped components.

The main project (application entry point) doesn't even have to have references to those DLL's. They will be loaded into your application by the container. An application can't get more loosely coupled than that.

That's a powerful approach since it allows you to build a plugin system without effort. Simply create a new class library where you place all your extension points (interfaces). Then reference that class library from each plugin and implement some/all extension points. I've described that approach (using ASP.NET MVC3) in detail in my blog.

You can also specify the lifetime of an object by using a property for the attribute:

The [Component] attribute should work in 99% of the cases (for your code). I strongly discourage you from specifying which services a class implement. If you have to specify the services, it's likely that you are breaking one of the SOLID principles. I suggest that you try to refactor your class (break it into smaller classes) and register each class with the [Component] attribute.

Modules

Sometimes it's impossible to use the [Component] attribute. For instance when you want to inject external dependencies in the container. For that you can either use the container directly to register the dependencies. But a much better solution is to let each module/section/namespace of your code manage it's own dependencies. It's quite easy. Simply create a new class and let it implement the interface IContainerModule like this:

You have now loaded all services which have been defined in modules which exists in any of the matching DLLs in the current directory.

You might wonder how you use the container later on in your application. There are nuget packages available for WCF, ASP.NET MVC3 which takes care of the integration for you. For other application types you need to manually create scopes and invoke the root classes (which in turn get their dependencies injected).

Domain events

Griffin.Container contains another feature which aids you greatly in keeping the coupling low between classes. And that's domain events.

Domain events are a weak events, which means that the subscriber cannot prevent the publisher from being garbage collected. Here is a great cartoon illustrating the problem with the .NET event model:

See? The UserService have no knowledge of the subscribers or what they does. Nor do the subscribers know or care where the event came from. That means that you can switch UserService for something else or add another subscriber without affecting the other parts.

Let's just look at the constructors of each class:

public UserCreated(User user)
public UserService(IUserRepository repos)
public UserWelcomeEmailSender(ITemplateGenerator templateGenerator)
public NotifyAdminsOfNewUser(ITemplateGenerator templateGenerator)

Can you tell what the classes are responsible of by just looking at the constructors? Of course. Small classes are a lot easier to understand and follow. Having full understanding of what a class does make it less likely that you introduce a bug when you fix/improve it.

This is very important. The container takes care of all dependency management and object creation for you, which means that it doesn't matter how many classes you create or how small they are. Hence the container promotes you to create small reusable classes which follows the SOLID principles (since you without effort can add them to the container).

Best practices

There are some practices which I'm using. Note that they are my very own subjective practices. They are based on my on experience (I've been using containers for about four years).

Avoid service Location

The container itself is a Service Locator. Which means that you can use service location, instead of constructors to find the services that you depend on. Something like this:

That's naughty. You can't tell that the Register method has a dependency without looking at the method code (or by invoking the method).

That becomes a maintenance nightmare when applications grow since the dependencies are hidden. You either have to inspect every method or invoke every execution path in every method to be sure that you have discovered and configured all dependencies correctly.

Simply put: Don't use service location if you can avoid it.

Depend on interfaces, not concretes

That's part of the D principle in SOLID (as in Dependency Inversion). Depending on interfaces (abstractions) instead of concretes (classes) makes it easier to refactor your code. You can for instance create a facade for the interface if you've decided to split the concrete into smaller classes (and break down the original interface into smaller interfaces). You would still have binary compability (and therefore only having to recompile and update the class library assembly).

There is nothing that says that there are a 1-1 mapping between a class and the interface that it implements. In fact, it's much better that you try to break down a class into smaller interfaces.

It will make code maintenance and refactoring a lot easier in the future.

Don’t choose a longer lifetime to get better performance

Complexity is tied to the lifetime. Long living objects have to care about thread safety and state management.

Let's take database transactions as an example. When having scoped objects you can simply register a Unit Of Work implementation as scoped. The UoW will automatically be used by all scoped objects (and therefore chare the transaction). The transaction will rolledback if SaveChanges() has not been called when the scope is disposed (and therefore the Unit Of Work). You can't do that with singletons since they live as long as the application.

Service2 takes service1 as a dependency which in turn requires a dbcontext. Let’s say that the dbcontext has an idle timeout which closes the connection after a while. That would make service1 fail and also service2 which depends on it.

Simply be careful when using different lifetimes.

Try to avoid primitives as constructor parameters

Try to avoid using primitives as constructor parameters (for instance a string). It’s better to take in object since it makes extension (subclassing) easier.

Using named dependencies are as fragile as using magic strings instead of constants.

A variable name doesn't really say that you are using different implementations for different classes, a factory do.

Avoid fat constructors

A fat constructor take several dependencies in it. It most often indicate a violation of Single Responsibility Principle. Refactor the class into smaller ones. Use domain events if you have to take actions when different things happen (as in the email example above).

I try to use a maximum of three parameters in my constructors.

Summary

I hope that I've at least made you understand a bit more about containers and why you should use them.

I could go on and on about code quality and why an inversion of control container aids you in increasing the quality. But I don't know if you would appreciate that. That's why I'm going to stop right here.

One question though - rather than parsing all the dll's to register to components, which loads them all into memory, what do you think about externalizing the dependency graph (or at minimum the list of dll's to register)? For example, if I have an Oracle component and a SQL Server component, I don't want to load both, but I may want to provide the dll's to both, depending on what the user's target DB is.