When we start a new project there are some utlity tasks, not related to the project’s target itself which we have to deal with. If we want a testable, easy-to-maintain and elegant code, we will need to implement #IoC and #DependencyInjection.

I’ve created a little multi-ioc-engine library that will take care of registering your interfaces or services for you, and any other additional class you need to, with the help of class attributes. It supports from scratch Autofac, Unity and nInject IoC containers.

Download the code from my repository at BitBucket with Git: http://repo.joanvilarino.info/diautoregistrationformvc
Or download it in a zip file: http://repo.joanvilarino.info/diautoregistrationformvc/downloads

The first thing you must know is that I created this library for a series of future articles, and at this point it only supports a small set of features, that I will be implementing in the following articles of the series. So, if you need something that’s not yet supported, feel free to add it yourself or wait for the “next episode”!

That being said, we start our nifty new awesome project, and we have to face dependency injection…

Most of the IoC tools available have extensions to deal with MVC projects, so you don’t have to manually register and resolve the controller classes, but you will still have to manually register all the interface dependencies those controllers have in their constructor.

When you are working on a little project, that’s not a big deal. You can always add a method in your Startup.cs class, and register your interfaces manually like this:


// Initialize container
var _kernel = new StandardKernel();
// Register type
_kernel.Bind<IMyInterface>().To<MyClass>();

But imagine that you have a big project with hundreds of interfaces. The method would grow up to unmaintanable proportions.

This little library will register the interfaces for you, allowing you to have a very small method that will do “all the magic”.

For this example, I’ve used a MVC5 template from Visual Studio 2013 Community Edition, so the library uses MVC5 tailored packages and the IDependencyResolver interface from MVC to implement controllers, but it should be easy to change it for another version or tipology of project.

Using my library, all the register process will be something like this:

private void ConfigureSimpleDependencyInjector(IDependencyInjectionEngine engine)
{
    new DependencyInjectionService(engine)
        .RegisterDependencies(new DependencyInjectionSetting()
        {
            AssemblyFilter = new List<string> { "DITest.", "DIRegistrationTest" }
        });
}

You can find this method (a little different but pretty the same) at the Startup.cs class of the MVC project.

Splitting it down, you can see it creates an instance of our DependencyInjectionService passing the IoC engine of our choice, then calling RegisterDependencies with a new DependencyInjectionSetting object.

The DependencyInjectionSetting object tells the library the preferences for the auto-registration process, using the following properties:

AssemblyFilter (Required)
This is a list of strings with the names or partial names of the assemblies we want to include in the registration scan for types. Once the library has the assemblies, will look for types that have been “decorated” with a special attribute DependencyInjectionRegisterAttribute, and register them in de IoC container.

If not specified, no type will be registered.

ExternalAssemblyFilter (Optional)
This property acts like the previous one, but whis time it will look for assembly files, allowing us to register types not referenced by our project. Don’t forget to include the .dll or .exe extension (we are looking for files here…)

If not specified, no external assemblies will be scanned on disk.

ClassesForcedToRegister (Optional)
Adding types to this list, you will force them to be registered. For example, if your engine of choice doesn’t auto-register Controller objects, you’ll need to add them in this list like this:

ClassesForcedToRegister = Assembly.GetExecutingAssembly().GetTypes()
                        .Where(t => typeof (Controller).IsAssignableFrom(t))
                        .ToList()

Selecting what types will autoregister
As I said before, the library will find the classes to register by himself. To do this, it implements two attribute classes that you will need to place in your class declaration.

Including types with DependencyInjectionRegister
If you want to include a type, add this attribute at type’s declaration.

    [DependencyInjectionRegister]
    public class MyService : IExternalService
    {
         // Class methods here...
    }

If your IoC doesn’t do it automatically, you could use this attribute in all your Controllers, or you could also use the ClassesForceToRegister attribute, for force adding them.

Excluding types with DependencyInjectionIgnore
If you add this attribute to any type, the library will ignore it and will not be auto-registered (unless it’s included in the list of ClassesForcedToRegister in DependencyInjectionSetting).

This is useful for the following situations:

  • When a class is added to the IoC container, it’s scanned for the interfaces it implements, and each of the interfaces found are registered for this class. If you don’t want some of these interfaces to get registered, add the attribute to the interface declaration.
  • When a interface is implemented in more than one class, you should use the attribute, letting only one class per interface to be auto-registered. If more than one class implements the same interface, the library will report an error.
  • When you want to custom register a class (change of lifetime or another not-yet-supported feature), you can add the attribute to ignore it and then register it manually.

Creating your controllers
Now that your app is fit to auto-register anything you throw at it, the real project coding part begins, and as the “good developer guide” says, the best way is injecting all services in the controller’s constructor… here goes an example:

    public class HomeController : Controller
    {
        private IExternalService _myService;
        private ILocalService _anotherService;

        public HomeController(IExternalService myService, ILocalService anotherService)
        {
            // Let's keep the injected services to use them later!
            _myService = myService;
            _anotherService = anotherService;
        }

        public ActionResult Index()
        {
            _myService.TerrificMethodOne();
            ViewBag.myServiceResult = _myService.SayHello();
            ViewBag.anotherServiceResult = _anotherService.GuessWhat();
            return View();
        }
    }

That’s all! No need to do anything else. If you marked all your services with the DependencyInjectionAttribute, they should implement the services they need recursively, and you won’t need to do a single new in your application at all!

Ok, I know how to use it, but… how is it done?
In following articles, I will try to explain some of the techniques used to create the library (how to use custom attributes, use of reflection to find out interfaces, classes and inheritance, how to create and inject “engines” for the library, and so on…). Just keep an eye – as I know you already do – in my blog and everything shall be revealed!

Thank you!
I really appreciate if you got that far and even more if you liked and / or plan to use it in a future.

Visit my repository at BitBucket of you want to see more example projects!!

Follow me

Joan Vilariño

Senior .NET Developer at Ohpen
Developer for more than 25 years and IT, gadget, mobile and electronics enthusiast working and publishing from Barcelona.
Follow me