Intro to Dependency Injection 5


A few weeks ago I had to privilege to present at the St Pete .NET Meetup in St. Petersburg Florida. The topic I chose is an important and interesting topic, at least in my mind. The presentation was well received, so I thought I might post an article here for a broader audience.

What exactly is Dependency Injection (DI) anyway? The great and powerful Wikipedia lists Dependency Injection as:

In software engineering, dependency injection is a software design pattern that implements inversion of control for resolving dependencies. A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it.

So what does that mean? Basically, we require a means to invert the relationship between objects within our systems.

Martin Fowler says:

The basic idea of the Dependency Injection is to have a separate object, an assembler, that populates a field in the [target] class with an appropriate implementation for the finder interface.

It loses a bit out of context, but the linked article is well worth the read.

Let’s look at some code.

In our first example, we’ve got a file=>new project, ASP.NET MVC in this case. Messages are hard coded in our controllers. Nothing fancy here.

        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }

In our next example we’ve got the beginnings of some logical separation. It’s still a simple file=>new MVC project, but we’ve got a Service handling the retrieval of the message for the actions in our controller. We’ll pretend that our service is hitting a database or something more interesting for our sample purposes.

        public ActionResult About()
        {
            var service = new SampleService();

            ViewBag.Message = service.GetMessage(2);

            return View();
        }

The problem here is that our HomeController now depends on the concrete implementation of the SampleService. This makes our code independently untestable. Every time you see the new keyword this is an indication that some refactoring may be needed.

For a first refactoring, you may choose to move the declaration out to a field level service and new-up the SampleService in the constructor, seen here:

    public class HomeController : Controller
    {
        private readonly SampleService _service;

        public HomeController()
        {
            _service = new SampleService();
        }

        public ActionResult About()
        {
            ViewBag.Message = _service.GetMessage(2);

            return View();
        }
    }

This may be a little cleaner, but still has the same inherent flaws as our previous example.

One method of DI, “Poor Man’s Dependency Injection” doesn’t require any additional frameworks to install. Let’s take a look:

    public class HomeController : Controller
    {
        private readonly ISampleService _service;

        public HomeController() : this(new SampleService())
        {
        }

        public HomeController(ISampleService service)
        {
            _service = service;
        }

        public ActionResult About()
        {
            ViewBag.Message = _service.GetMessage(2);

            return View();
        }
    }

Here we’ve got an additional constructor that accepts an Interface. This allows us remove the dependency on the concrete implementation of the SampleService. You may have noticed we’ve also added to our default constructor, the instantiate a new SampleService if one is not supplied. This allows us to supply our own implementation for testing purposes, should the need arise.

You can see in our next example that this will work through multiple levels of our system:

    public class SampleService : ISampleService
    {
        private readonly IRepository<string> _repository;

        public SampleService() : this(new Repository<string>())
        {
        }

        public SampleService(IRepository<string> repository)
        {
            _repository = repository;
        }
    }

Now, I’m not a fan of this method. It’s ugly and a bit confusing when you first see it. There are better, more readable options available to us.

 

Unity

Unity languished under Microsoft for a number of years. Thankfully it’s under new control now and seems to have had new life breathed into it. Unity offers a feature rich, highly configurable option for DI.

For our purposes we’ll install the nuget package, Unity.Mvc. Open the UnityConfig.cs file located in the App_Start folder and register our types.

        public static void RegisterTypes(IUnityContainer container)
        {
            container.RegisterType<ISampleService, SampleService>();
            container.RegisterType<IRepository<string>, Repository<string>>();
        }

Now we don’t need our Poor Man’s constructor anymore. Everything is much cleaner now.

Read more on Unity, here.

 

Ninject

I like Ninject for a lot of reasons. One of which, of course, is their fancy ninja guy. Ninject isn’t quite as feature rich as Unity, but offers more in way of performance. Some speed tests I’ve seen have Ninject operating at nearly twice the speed of Unity in some instances. Configurations in code are similar to Unity as well. Let’s install the nuget package, Ninject.MVC5, and take a look at the NinjectWebCommon.cs file.

        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            try
            {
                kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
                kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

                RegisterServices(kernel);

                DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));

                return kernel;
            }
            catch
            {
                kernel.Dispose();
                throw;
            }
        }

        /// <summary>
        /// Load your modules or register your services here!
        /// </summary>
        /// <param name="kernel">The kernel.</param>
        private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<ISampleService>().To<SampleService>();
            kernel.Bind<IRepository<string>>().To<Repository<string>>();
        }

For more on Ninject, and their neat little ninja guy, click here.

 

Autofac

Perhaps the most performant DI framework is Autofac. Boasting the fastest speeds in most available tests, this also happens to be my favorite. I also believe they have the best, most comprehensive collection of online documentation.

I haven’t found a nuget package that includeds a config file, so we’ll start with the Autofac.Mvc5 package and then make our own AutofacWebCommon.cs file.

    public static class AutofacWebCommon
    {
        public static void RegisterDependencies()
        {
            var builder = new ContainerBuilder();

            builder.RegisterType<Repository<string>>().As<IRepository<string>>();
            builder.RegisterType<SampleService>().As<ISampleService>();

            builder.RegisterControllers(typeof(MvcApplication).Assembly);

            var container = builder.Build();

            var resolver = new AutofacDependencyResolver(container);

            DependencyResolver.SetResolver(resolver);
        }
    }

More on Autofac, and their awesome documentation, can be found here.

###

But, I want to hear from you out there. What are your favorite DI/IoC frameworks?  What tips and tricks do you have for those new to DI?

Source and slidedeck can be found here.

 


Please Consider Sharing This Post:

FacebooktwitterredditlinkedinFacebooktwitterredditlinkedin