From Static to Flexible

Back in the “good old days” static classes and singletons where widely used patterns. They could be called from anywhere and you didn’t have to spend a thought on dependency management. Or unit testing. Because most often you couldn’t test code that called methods on those objects. They usually needed config files, databases, web-services, message queues, more files, network shares … just about anything. And none of that plays nice with unit tests. Pity that these days can also be called “earlier this year”…

As a “tame” example of such a static object think of the File class. Now imagine you have a component that uses File.Exists(). How do you test that code? Do you really want to create a file whenever you try to run a test of your component?

Lets look at a sample to show how you can still test that code.

public class MyComponent
{
  public void DoIt(string pathToFile)
  {
    if(File.Exists(pathToFile)) { /* ... */ }
    else { /* ... */ }
  }
}

In order to simulate the situation where the file exists you would have to create said file. That’s not what unit tests are for. They should be almost effortless to write. Wrestling with the file systen in a unit test scenario is definitely not effortless.

A common recommendation is to write a wrapper for the File class which is non-static. That would look like this:

public class FileWrapper
{
  public bool Exists(string path)
  {
    return File.Exists(path);
  }
}

But that’s not the whole story. We need a way to simulate the result of FileWrapper.Exists() or we would just add code but won’t gain anything. To do that we lend ourselves the solution Microsoft used for HttpContext. We introduce a base class with all virtual properties and methods.

public class FileBase
{
  public virtual bool Exists(string path)
  {
    throw new NotImplementedException();
  }
}
public class FileWrapper : FileBase
{
  public override bool Exists(string path)
  {
    return File.Exists(path);
  }
}

Now we change our component to use some instance of FileBase instead of the static File class.

public class MyComponent
{
  private readonly FileBase file;
  public MyComponent(FileBase file)
  {
    this.file = file;
  }
  public void DoIt(string pathToFile)
  {
    if(this.file.Exists(pathToFile)) { /* ... */ }
    else  { /* ... */ }
  }
}

We can use Moq or some hand-crafted test double that implements FileBase to simulate the existance or non-existance of said file very easily.

To make things a bit nastier imagine that MyComponent is used throughout a large legacy codebase. You just changed the signature of it’s constructor. Now you would have to change all calls to that constructor immediately or the system will be broken. That’s not an option.

But if we add a constructor overload that delegates to the constructor we just created and uses the default implementation for FileBase we can leave all calls to the default constructor in place but still have the improved testability of the constructor that follows the Dependency Injection Pattern.

public class MyComponent
{
  private readonly FileBase file;
  public MyComponent() : this(new FileWrapper())
  {
  }
  public MyComponent(FileBase file)
  {
    this.file = file;
  }
  // more code
}

I know that this solution is not pure. The DI Pattern advocates the usage of one constructor only that takes all the dependencies of a class. I prefer that as well. But “legacy enterprise systems” are rarely what I’d call clean and sometimes you have to take some dirty intermediate steps towards clean solutions. With the technique outlined above you can improve such systems one step at a time. You can control how far these improvements are visible by adding or removing constructors that create default implmentations for their dependencies and replacing calls to these default constructors one at a time. Rome wasn’t built in a day…

Advertisement

Fun with constructor arguments Part 2.1: Anonymous overrides revisited

After publishing the post on Anonymous overrides I thought about the topic again. In the end it didn’t make sense to put that functionality in a separate class.

The SmartConstructor already does most of the heavy lifting and matching the properties of an anonymous object to constructor parameters can easily be encapsulated in a new ParameterMatchingConvention.

As a result the SmartConstructor grew by a few lines of code (reading the properties of the anonymous object and converting them to ConstructorParameters) and I created a new convention called StringAsMappingNameMatchingConvention.

Get the overhauled source code for the SmartConstructor here (project TecX.Unity folder Injection and the test suite that shows how to use it in TecX.Unity.Test).

Fun with constructor arguments Part 3: Named registrations

A while ago there was a question on StackOverflow: If I have multiple implementations of an interface registered as named mappings and a constructor that should consume such a named mapping how can I tell Unity to automatically match the argument name to the mapping name?

E.g. if you have the following class definitions:

public interface ICommand { }

public class LoadCommand : ICommand { }

public class SaveCommand : ICommand { }

public class Consumer
{
  public Consumer(ICommand loadCommand, ICommand saveCommand)
  {
    // ...
  }
}

Now you setup your container and register both command implementations:

container.RegisterType<ICommand, LoadCommand>("loadCommand");
container.RegisterType<ICommand, SaveCommand>("saveCommand");

And when you resolve the Consumer the LoadCommand should be used for the parameter named loadCommand and the SaveCommand should be used for the parameter named saveCommand.

This is what you would have to do using Unity as is:

container.RegisterType<Consumer>(  new InjectionConstructor(
  new ResolvedParameter(typeof(ICommand), "loadCommand"),
  new ResolvedParameter(typeof(ICommand), "saveCommand")));

And this is a “slightly” enhanced version:

container.RegisterType<Consumer>(new MapParameterNamesToRegistrationNames());

The class MapParameterNamesToRegistrationNames is derived from InjectionMember. It places a marker policy in Unity’s build pipeline. When an object is resolved by the container a custom BuilderStrategy looks for that marker. If the marker is found the strategy will replace the dependency resolvers (implementations of IDependencyResolverPolicy) that Unity puts into the pipeline by default with NamedTypeDependencyResolvers using the name of the constructor argument as name of the mapping.

public class MapParameterNamesToRegistrationNamesStrategy : BuilderStrategy
{
  public override void PreBuildUp(IBuilderContext context)
  {
    if (context.Policies.Get(
      context.BuildKey) == null)
    {
      return;
    }
    IPolicyList resolverPolicyDestination;
    IConstructorSelectorPolicy selector =
      context.Policies.Get(
        context.BuildKey, out resolverPolicyDestination);
    if (selector == null)
    {
      return;
    }
    var selectedConstructor = selector.SelectConstructor(context, resolverPolicyDestination);
    if (selectedConstructor == null)
    {
      return;
    }
    ParameterInfo[] parameters = selectedConstructor.Constructor.GetParameters();
    string[] parameterKeys = selectedConstructor.GetParameterKeys();
    for (int i = 0; i < parameters.Length; i++)
    {
      Type parameterType = parameters[i].ParameterType;
      if (parameterType.IsAbstract ||
          parameterType.IsInterface ||
          (parameterType.IsClass && parameterType != typeof(string)))
      {
        IDependencyResolverPolicy resolverPolicy =
          new NamedTypeDependencyResolverPolicy(parameterType, parameters[i].Name);
        context.Policies.Set(resolverPolicy, parameterKeys[i]);
      }
    }
    resolverPolicyDestination.Set(
      new SelectedConstructorCache(selectedConstructor), context.BuildKey);
  }
}

The registration code tells you exactly what you expect from the container. No confusing setup of InjectionConstructors and ResolvedParameters. Just another simple convention that can make your life a lot easier.

Get the source code for MapParameterNamesToRegistrationNames here (project TecX.Unity folder Injection and the test suite that shows how to use it in TecX.Unity.Test).

Fun with constructor arguments Part 2: Anonymous overrides

An interesting feature of Castle Windsor is the ability to specify parameter overrides for a constructor using anonymous objects.

You define an anonymous object with properties named like the parameter you want to override and assign some value to it. You can either directly provide a value for that parameter or the name of a mapping you registered for the type of that parameter.

That means if you have a class with a dependency like this one:

public class MyService : IMyService
{
  public IFoo SomeFoo { get; set; }
  public MyService(IFoo someFoo)
  {
    this.SomeFoo = someFoo;
  }
}

and two classes that implement IFoo called Foo and Bar. Foo is registered as the default mapping (without a name) and Bar is registered as an additional mapping for IFoo with the name “Bar”:

container.RegisterType<IFoo, Foo>();
container.RegisterType<IFoo, Bar>("Bar");

You can use the AnonymousParameterOverride to specify that you want to use the named mapping instead of the default one:

container.RegisterType<IMyService, MyService>(new AnonymousParameterOverride(new  { foo = "Bar" });

Now this looks a little bit better than the default way Unity offers you to do this which is something like this:

container.RegisterType<IMyService, MyService>(
  new InjectionConstructor(new ResolvedParameter(typeof(IFoo), "Bar"));

But still not quite as fluent as I would like to see it. Unity does not really have a fluent configuration API but I took the liberty to write one.
The ConfigurationBuilder will be the subject of a series of posts on its own so for now let me just show you a glimpse at what is possible with it:

ConfigurationBuilder builder = new ConfigurationBuilder();
builder.For<IMyService>().Use<MyService>().Ctor(new { foo = "Bar" });

Much better isn’t it?

Get the source code for the AnonymousParameterOverride here (project TecX.Unity folder Injection and the test suite that shows how to use it in TecX.Unity.Test).