Griffin.Container is a somewhat performant Inversion of control container. It's goal is not to be the fastest container nor the one with the most feature rich API.

Instead I've tried to take a convenience over configuration approach. You'll probably have to design your applications better instead of using a lot of container features https://www.codeproject.com/script/Forums/Images/smiley_wink.gif. For more information about best practices read my previous IoC / Dependency injection article.

The goal with this article is to show you the powers of Griffin.Container and it's hopefully easy API. A quick note on the samples zipfile: The samples are complimentary to the article. Both read the article and download the zip to get the most out of everything.

Let's start with an easy hello world project.
Create a new console project and run "install-package griffin.container" from the package manager console. Then add the following code:

The container uses something called scopes for this. A scope simply means that the container keeps track of all created objects that have a limited lifetime. The actual lifetime ends when you dispose the scope. A scope is used like this:

You'll see that four objects will be created and disposed for you. Scoping is very useful for request/reply style of applications (for instance web applications or web services) since everything will be created and cleaned up automatically for you. No more need to manage state manually.

A design decision that I made with Griffin.Container is to never allow you to create scoped objects from the main container like this:

That example will throw an exception since you have configured Hello to be scoped but creating it in the main container which will effectivly make it a singleton. That's a dormant bug. The Hello class could have used a TCP connection or a database connection. Those may not be open for ever, hence the class would fail for all subsequent calls when the connection is dropped (since the connection state is not managed because the class was not designed to be long lived).

Working with interfaces

When starting using an IoC container you'll probably want to start using interfaces more frequent too. With a container you'll never have to care about more than the class contract (which usually is an interface). That is, you'll never have to know how or when you should create and dispose an object. The container takes care of that for you.
Let's let Hello implement one more interface:

The great thing with keeping interfaces small and well defined is that they are easy to reuse and implement. The following snippet is all which is required to print the state from all classes that implements the interface:

Do note that you do not have to do anyting special to register Hello as an implementation of IPrintState. The method registrar.RegisterConcrete<hello>()</hello> will register the class as all non .NET interfaces.

Dependency injection

The previous examples did only show you how you can create objects and control the object lifetimes. That's the inversion of control part. However, IoC containers are also useful for dependency injection. That is to identify and pass all dependencies to your classes.

This is usually done using constructor injection (which also is the only supported method in Griffin.Container). Constructor injection is useful since you directly can identify which dependencies a class has.

The difference is that the first example is not tied to a specific implementation (data source). We can also control the lifetime of the repository independently of the user service instances. We can for instance let all UserService instances share the same repository instance to be able to do caching inside it.

As for the registrations, you do not have to do anything special to take advantage of dependency injection. The container handles it automatically for you. Remember to prefer interfaces over classes as dependencies. And try to keep them as small as possible to make the code more flexible and easier to refactor.

Best practice

Depend on abstractions (interfaces) instead of concretes (classes). Your application get's easier to refactor. Try to divide your interfaces into smaller pieces. For instance the IUserRepository could be IUserQueries and IUserStorage. They could however still be implemented by the same class (but the queries could be moved, cached etc later on without having to modify the dependent code).

Registrations

The registration process is where all containers differs. I recommend that you do not register every single class manually (by invoking one of the registrar.RegisterXXX() methods). Sure. You should avoid change/refactor code (be SOLID). But in reality there are a very few of us which can write code so that no refactoring is required. Instead we do change our classes. Those changes will affect the registrations. The best way to keep them in sync is to manage the registrations (lifetime) from the classes themselves.

Best Practice

Use the [Component] attribute where it's possible. It's both visible in sandcastle generated documentation and makes it easier to refactor the application. Try to use the same lifetime for all classes if possible (i.e. do not specify it in the attribute but in the LoadComponents() line).

A link to the online documentation can be found at the bottom of this article.

RegisterComponents

Used to register all classes which has been tagged with the [Component] attribute. It can either scan one/more specified assemblies or load/scan assemblies in a specific folder.

RegisterModules

Modules are a great way to move the registration process from one single location into several and by doing so allow each module in your system to be in charge of it's own registrations. That makes your application easier to mantain and it gives you an better overview of what each module registers.
I'll come back to modules later.

RegisterService

Register an service (typically an interface) using a custom factory method. Typically only used to register external dependencies (such as db libraries) in the container.

RegisterType

Register a specific service (interface) to a specific concrete (class). Typically only used to register external dependencies (such as db libraries) in the container.

RegisterInstance

Register a singleton which has already been created somewhere.

Modules

Griffin.Container allows you to use modules to move the registration responsibility from a single location to each module/package in your application. All you need is to create a new class and let it inherit IContainerModule.

Plugin architectures becomes obsolete (unless you have to be able to disable/unload plugins) with this technique. Simply drop a new assembly in the app folder and restart the application.

Best practice

Use a composition root in every project, use it to call registrar.RegisterComponents() for the current assembly (i.e put a ContainerModule in the root namespace of the project).

Domain events

Griffin.Container has built in support for domain events (handled within the same process). Domain events means that you send an event when something have happened. For instance UserCreated, AccountLocked, ReplyPosted etc. Those events enables you to create loosely coupled applications. You could for instance subscribe on the event ReplyPosted to be able to send out email notifcations (without having to change the class(es) that created/saved the reply).

The difference between the event model in .NET and the event model in Griffin.Container is that the latter is loosely coupled.

Avoid attaching domain objects/models to the events, but try to treat the domain events as immutable DTO's instead. It makes it a lot easier if you have to scale your application later on. You can always load the correct domain model through the repositories/queries when you receive the domain event.

Commands

Griffin.Container do also have a built in command pattern implementation. I've chosen to seperate the actual handling (ICommandHandler<T>) from the command class (ICommand). That enables us to handle the command anywhere. You can for instance start by handling all commands in the same server/process but later on route some commands to a different server.

Always try to create one command per use case instead of creating small commands which you chain. Chained commands will most likely lead to a mess when the application grows.

As I mention before we can scale the application by moving the command handling to different processes. To enable that we have to treat all commands as asynchronous. That means two things:

A command can never return something.

Don't expect the command to have been executed just because ICommandDispatcher.Dispatch() has returned.

Instead wait for the domain events and use those for the extra processing.

Setup

The command dispatcher do not have a default implementation. Instead we have to assign one. There is a built in one which is called ContainerDispatcher. As you might have guessed that it uses the IoC container to find the correct handler.

CommandDispatcher.Assign(new ContainerDispatcher(myContainer));

However, since commands typically are executed from services, controllers etc I do recommend that you register the ICommandDispatcher implementation in the container and get it through dependency injection. (although the dispatcher could be considered to be an infrastructure component, up for discussion).

A command

A command is a regular .NET class which is used to transfer the command and it's arguments to a command handler.

Notice that the userName is passed in the constructor (and has a private setter) while DisplayName can be set through the property. That indicates that the UserName is mandatory while the DisplayName is optional. Always try to follow this pattern since it makes easier to tell which information is required.

Handling a command

A command is handled by classes that implement the IHandlerOf<T> interface:

In this example I used a repository, but it could have been vanilla ADO.NET or a webservice. It really doesn't matter since no code is dependent on the implementation.

Invoking a command

Simple:

CommandDispatcher.Dispatch(new CreateUser("arne"));

I do recommend that you register the dispatcher in the container and take it as a dependency in your own classes. It makes the intent more clear (even though it can be considered to be a infrastructure dependency).

Do note that all intercepted classes must have virtual methods for it to work (limitation by the Castle.Proxy).

Register the decorator in your container:

container.AddDecorator(new ConsoleLoggingDecorator());

Let's try it with our repository:

container.Resolve<IUserRepository>().Get(10);

The console prints:

Get(10)

Be aware of that decorators hurt performance. But not as much as you would think (google performance benchmarks castle proxy).

Built in decorators

There are one decorator built into the Interception package.

Exception logger

This decorator will intercept all classes and log all exceptions together with the method name and all argument values.

Sample output:

SampleApplication.Users.UserService.Get(10) threw an exception:
(exception info would be here if this were not an article, which it is)

The exception will of course still be thrown. It's up to you to handle it.

(The decorator where just added to illustrate how you can create your own)

Decorator summary

Combining command handlers and decorators can be really useful. You can for instance validate all commands using DataAnnotations with a decorator before the real handler is invoked. That's validation in one decorator instead of in every command handler. You could also create a command handler decorator which takes care of the database transaction.

Extending the container

I've avoided extension methods like the pest in the core since extension methods prevent extension through inheritance (which you all know is one of the foundations of OOP). The core itself has been divided into three interfaces.

Feel free to check the source code when reading this section, since it will make a lot more sense then.

The first on is the IContainerRegistrar. It's purpose is to expose the registration interface used when register services and concretes in the container. That's it's only responsibility. Everything registered is exposed by the Registrations property.

The next interface is the IContainerBuilder. It's purpose is to analyze all registrations and create build plans (IBuildPlan) for each service. The build plan is used to create/access all classes that implements a service. To do that it stores an IInstanceStrategy for each concrete/class. The stategy decides when it's time to create a new instance and when it should fetch it from the storage.

The final part is the service location. The core interface is IServiceLocator which contains the basic resolution methods. It's inherited by IParentContainer which adds the CreateChildContainer() method and by the IChildContainer interface which also inherits IDisposable.

Framework libraries

There are also some framework libraries which you can use for your favorite framework.

Thanks for this article! I've looked at some IoC, DPI containers, but somehow this one escaped my attention.I'm a bit wary though that all configuration in your examples was in code. I personal use Spring.NET since I actually started out with Java, so I already knew that container. What I like about Spring IoC,DPI is that you can write XML configuration files and thus build up a complete application at the time when an object is requested from the container. By adhering to the principle of programming against interfaces, it easy to exchange parts of your application by merely rewriting the XML configuration file. There's no need to recompile the complete application.To make a long story short: "Is there a way to also have that kind of configuration per file in Griffin.Container?"

Why isn't the module/[Component] registration features enough for you?

To be honest, I'd have to say: "Because I'm used to doing it that way". This is definitely not a good argument. I'd have to play around a bit with your solution and try to use it in one of my projects where I had used Spring.NET's XML configuration files, to really find out if the configuration aspect is relevant anymore.