Showing posts with label IoC. Show all posts
Showing posts with label IoC. Show all posts

Tuesday, 21 May 2013

AutoFac Dynamic Factories

AutoFac like many Ioc containers make it easy to declare your dependencies and just get them magically injected for you. The problem comes in when trying to control the lifetime of certain objects, especially if you are trying to create some shorter lifetime objects. Once you declare your dependency you don't have any more control over the lifetime of it. Also sometimes you might specifically need 2 different instances of an object. AutoFac just like many other containers has lifetime options when registering objects:
builder.RegisterType<TestClass1>().InstancePerDependency();
builder.RegisterType<TestClass2>().InstancePerLifetimeScope();
The first indicates that each dependency or call to the Resolve() method will give you a new instance. The 2nd indicates that each dependency or call to the Resolve() within the same lifetime scope will give you a new instance. This is sort of special as it actually shares the instance in the same call graph, lifetime scope or call to container.BeginLifetimeScope(). So this registration of specific to when sharing instances is preferred.

So even if you change all your objects to InstancePerDependency lifetime (which would be hugely limiting anyway) you still need a way to create these on-the-fly instances. The AutoFac solution is to resolve an object of type Owned<T>

However this means having the reference to the IContainer in your objects which is very bad and IOC 101 dont's. So just create a simple interface for your framework that you can use to inject abstract factories instead something like:

public interface IFactory<T>
{
    T Create();
}

This is very simple and easy to generate mocks for testing. You can also easily create a generic wrapper using lambda expressions to generate on the fly even when not using AutoFac or a different container. But for the autofac version, you can call it anything you like AutoFacFactory if you like, but it will function something like this:

public class Factory<T> : IFactory<T>
{
 private IContainer _container;

 public Factory(IContainer container)
 {
  _container = container;
 }

 public T Create()
 {
  var owned = _container.Resolve<Owned<T>>();
  return owned.Value;
 }
}
In order to get this to work there's a few simple steps to configure AutoFac:

First register the open generic type:

var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(Factory<>)).As(typeof(IFactory<>)).InstancePerDependency();

Next is that you have to actually register the container instance itself back to the container, as it seems its not automatic. This can actually be done easily but you need to construct a builder to update the container:

var postContainerBuilder = new ContainerBuilder();
postContainerBuilder.Register(c => container);
postContainerBuilder.Update(container);

Now you can declare dependencies to IFactory of any type that is registered and be able to create unique instances each time:

var builder = new ContainerBuilder();
builder.RegisterType<TestClass1>().InstancePerDependency();
builder.RegisterType<TestClass2>().InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(Factory<>)).As(typeof(IFactory<>)).InstancePerDependency();

var container = builder.Build();

var postContainerBuilder = new ContainerBuilder();
postContainerBuilder.Register(c => container);
postContainerBuilder.Update(container);

var factory1 = container.Resolve<IFactory<TestClass1>>();
var factory2 = container.Resolve<IFactory<TestClass2>>();

var t11 = factory1.Create();
var t12 = factory1.Create();

Assert.AreNotEqual(t11, t12);

var t21 = factory2.Create();
var t22 = factory2.Create();

Assert.AreNotEqual(t21, t22);

Sunday, 4 December 2011

IoC for ASP.NET

With my last post where I showed what and how you could create your own IoC container, I was literally inundated by criticism from 1 developer. The criticism was that the I lacked a good example and the why.

What I wanted to do in this post is to show how you can do this in an old ASP.NET application. As for answering the why, there are plenty of posts like this one, with very good discussions and reasoning in both directions.

Now first let me repeat the most important idea. The idea is to use DI, and an IoC Container is just a tool to help achieve this.

There are other benefits like for instance the ability to replace object mappings in one place instead of refactoring code in many places to replace one type for another.

In the stackoverflow post you can scroll down to Joel Spolsky's comment, and just read the reasoning behind why you shouldn’t care about this and stop reading and be done.

But if you're interested to see how this can be done in ASP.NET, and maybe you can spot what you like about it then keep reading.

I found some solutions but not many that I liked or felt that it was good enough and a lot ended up needing a hack here and there.

So let me start by what I wanted to achieve. To Illustrate I will create this very simple page.

Code Snippet
  1. public partial class MyDIPage : System.Web.UI.Page, IDIExampleView
  2. {
  3.     private DIExamplePresenter _presenter;
  4. }

This page uses an MVP pattern, so the page implements a view that will be used by the presenter.

Code Snippet
  1. public interface IDIExampleView
  2. {
  3.     string Data { get; set; }
  4. }

And this is the presenter.

Code Snippet
  1. public class DIExamplePresenter
  2. {
  3.     private IDIExampleView _view;
  4.     private DIExampleDao _dao;
  5.     public DIExamplePresenter(
  6.         IDIExampleView view,
  7.         DIExampleDao dao)
  8.     {
  9.         this._dao = dao;
  10.         this._view = view;
  11.     }
  12. }

This page also needs a presenter so normally I would just construct one as follows:

Code Snippet
  1. this._presenter = new DIExamplePresenter(this, new GenericDao(new SqlContext));

There are also dependencies to a IDataContext, and potentially 2 different implementations that I made up for this example but it would be similar in the real world.

What I wanted instead is for the Global.asax to be the composition root as apposed to each individual page . This is the place we compose our object graph.

So this means that we can now instead of newing up or figuring out where to get our dependencies in each page, we can simply define our constructor and ask for the dependencies we need.

Code Snippet
  1. public MyDIPage(DIExamplePresenter presenter)
  2.     : this()
  3. {
  4.     this._presenter = presenter;
  5. }

Now my page can simply get the dependencies passed in instead of trying to new it up.

For this to work though I need to put a little bit of framework in place.

You will need to create a handler factory, this is not really that complex, well actually it’s as simple as copy and pasting some sample code off some guys blog post like this one. All the instructions and code are there, and then it is not very hard to modify it to work for your case. In the blog post he is using the common service locator to resolve components, but I have created a different flavour which I will show you next.

The article shows exactly how to add the handler class and what to add to the config.The most important part of the article and the handler is the GetHandler that will be called when a page is requested. This will get a page instance and pass it to a function to inject dependencies. A little bit like this:

Code Snippet
  1. private void InjectDependencies(object page)
  2.         {
  3.             Type pageType = page.GetType().BaseType;
  4.  
  5.             var ctor = GetInjectableCtor(pageType);
  6.  
  7.             if (ctor != null)
  8.             {
  9.                 var supportedInterfaces = ExtractViewInterfaces(pageType);
  10.  
  11.                 object[] arguments = (
  12.                     from parameter in ctor.GetParameters()
  13.                     select GetInstance(parameter.ParameterType, supportedInterfaces, page))
  14.                     .ToArray();
  15.  
  16.                 ctor.Invoke(page, arguments);
  17.             }
  18.         }

Each one of the page dependencies will then be resolved by a function called GetInstance where we will use StructureMap to resolve it.

Instead of using the Common ServiceLocator we will just reference our Ioc container of choice. This for me turned out to be StructureMap . Why? Because it was VERY easy to use and seems to fit very well with ASP.NET. You can follow the link or simply in your visual studio extension manager find the nuget package and add it.

So now we have a handler factory, and we can set up structure map:

Code Snippet
  1. public class Global : System.Web.HttpApplication
  2.   {
  3.       void Application_Start(object sender, EventArgs e)
  4.       {
  5.           // Code that runs on application startup
  6.           ObjectFactory.Initialize(x =>
  7.               {
  8.                   x.For<IDataContext>().Use<MemoryContext>();
  9.                  
  10.               });
  11.       }
  12.   }

You will see that I did not register anything for Presenter and GenericDao. That is because these are concrete types, structuremap can simply activate them with reflection. I could of course remap GenericDao to another subclass, but to keep things simple I wont be doing this.

So now we can simply resolve dependencies in the handler factory:

Code Snippet
  1. public class CustomPageHandlerFactory : PageHandlerFactory
  2. {
  3.      private object GetInstance(Type type)
  4.      {
  5.          return ObjectFactory.GetInstance(type);
  6.      }
  7. }

But wait there is a problem:

If you look at the page now its constructor has a dependency on Presenter, and Presenter has a dependency on the Page. We have a circular dependency. This is one of the main reasons that if you search for solutions you will find plenty of ones using property injection instead to avoid this. But because we have an empty parameterless constructor which is called first we can still set the instance first and then inject the dependencies via the overloaded constructor.

One other thing that is a problem is that the dependency is actually to the view interface and not the page type which the handler created.

So to make this work for the Views in the MVP framework they must have one ultimate ancestor. If you have more than one you could also define this in the handler factory if you have to but this is what I did:

Code Snippet
  1. public static List<Type> ExtractViewInterfaces(Type type)
  2. {
  3.     var supportedInterfaces = new List<Type>();
  4.  
  5.     foreach (var intf in type.GetInterfaces())
  6.     {
  7.         if (typeof(IView).IsAssignableFrom(intf))
  8.         {
  9.             supportedInterfaces.Add(intf);
  10.         }
  11.     }
  12. }

What this function does is extract all the view interfaces from the page type and then before resolving the page I tell StructureMap to use special explicit arguments to replace the view dependencies now the handler factory's getinstance looks like this:

Code Snippet
  1. private object GetInstance(Type type, List<Type> supportedInterfaces, object pageInstance)
  2. {
  3.     ExplicitArgsExpression expression = null;
  4.     foreach (var intf in supportedInterfaces)
  5.     {
  6.         if (expression == null)
  7.         {
  8.             expression = ObjectFactory.With(intf, pageInstance);
  9.         }
  10.         else
  11.         {                  
  12.             expression = expression.With(intf, pageInstance);
  13.         }
  14.     }
  15.  
  16.     var instance = expression == null ? ObjectFactory.GetInstance(type) : expression.GetInstance(type);
  17.  
  18.     return instance;
  19. }

Now you can simply declare your dependencies in the constructor of the page. Whether you add constructor dependencies, or move them around. And best of all it doesn’t interfere with existing non DI pages, and there is no deep dependency on the container its just simple clean DI.