Humblecoder

Caution, this blog may be ironically named

Basic Dependency Injection

| Comments

During my travels in unit testing I have repeatable come across Dependency Injection and IoC. I have been using constructor dependency injection inside a WinForms MVC project. This was working well but I ended up with a large number of constructor parameters for controllers that have dialogs.

Not quite liking the ‘parameterful’ constructors, I looked towards one of the many IoC frameworks. I like the look of Autofac and it’s almost sexual syntax but for this application I want to keep it as a single executable with no external dependencies, ruling them out for now. Also, there is a lot more learning for me in this area. I don’t fully understand the life cycles of the objects or how to create objects without passing around the IoC container to create them from.

I came across this blog post which implements an IoC container in a mere 33 lines. It uses a static class with three functions, generics and a private dictionary. I like the look of this and it appeared to remove my need to pass in all the dependencies to the constructors. But it is static and would make injecting mocks difficult. Also, I could register types with the container and only produce new objects, I regularly construct full mock or stub objects which return predefined results configured during the test setup. So I used this as a starting point and created my own instance based container. I ended up with is:

view plaincopy to clipboardprint

  1. public interface IClassFactory
  2. {
  3. void RegisterType<TContract, TImplementation>();
  4. T ManufactureType();
  5. }
  6. public class ClassFactory : IClassFactory
  7. {
  8. private readonly IDictionary<Type, Type> types = new Dictionary<Type, Type>();
  9. public virtual void RegisterType<TContract, TImplementation>()
  10. {
  11. types[typeof(TContract)] = typeof(TImplementation);
  12. }
  13. public virtual T ManufactureType()
  14. {
  15. return (T)Resolve(typeof(T));
  16. }
  17. public virtual object Resolve(Type contract)
  18. {
  19. if (types.ContainsKey(contract))
  20. {
  21. Type implementation = types[contract];
  22. ConstructorInfo constructor = implementation.GetConstructors()[0];
  23. ParameterInfo[] constructorParameters = constructor.GetParameters();
  24. if (constructorParameters.Length == 0)
  25. return Activator.CreateInstance(implementation);
  26. List parameters = new List(constructorParameters.Length);
  27. foreach (ParameterInfo parameterInfo in constructorParameters)
  28. parameters.Add(Resolve(parameterInfo.ParameterType));
  29. return constructor.Invoke(parameters.ToArray());
  30. }
  31. throw new ArgumentException(“contract is not a known type”);
  32. }
  33. I pretty much took the code from the above blog and amended it slightly to use an interface and throw a new exception when the type was unknown. This allows types to be registered and when a request is made for a new instance it loops over the constructor parameters and creates the dependencies, finally returning the new object with its full object graph.

    To use this I registered all the types with a ClassFactory instance in Program.CS file then passed in the container to the main application controller. I have read extensively that you should not pass around container and my ‘clever’ workaround was to call it a ClassFactory so it’s no longer a container :)

    On more serious reflection the passing of the class factory looks, and feels, like the service locator pattern and is a perfectly acceptable approach. I have a feeling that this will be a running theme as I delve deeper into the world of IoC.

    For unit testing I subclassed the concrete class factory from above. This new class allowed instantiated objects to be registered with it and return them as required. The code for this looks like:

    view plaincopy to clipboardprint

    1. public class UnitTestClassFactory : ClassFactory
    2. {
    3. protected Dictionary<Type, Object> m_ObjectList = new Dictionary<Type,Object>();
    4. public void ReturnObjectForType(Object returnedObject)
    5. {
    6. m_ObjectList.Add(typeof(T), returnedObject);
    7. }
    8. public override T ManufactureType()
    9. {
    10. if (m_ObjectList.ContainsKey(typeof(T)))
    11. {
    12. return (T)m_ObjectList[typeof(T)];
    13. }
    14. else
    15. {
    16. T returnedObject = default(T);
    17. try
    18. {
    19. returnedObject = base.ManufactureType();
    20. }
    21. catch (ArgumentException)
    22. {
    23. //This means we don’t know about the type so just return the default
    24. }
    25. return returnedObject;
    26. }
    27. }
    28. }

    This allows me to create mocks with RhinoMocks, set up the return values and then inject them into the system under test. I suppose there is no reason why this could not be the actual implementation used by the application and it would provide Singleton support. (As an aside, I dislike singletons unless you have a very very good reason for one)

    So there you have it, the basic IoC / DI method used in my tiny little application. I know full on IoC containers provide a lot more and I’ve probably missed the point somewhere in here but it’s a good start. Feel free to point out the errors in my way!

    Comments

    Copyright © 2013 - Will - Powered by Octopress