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

Inject Primitive Dependencies by Convention

Mark Seemann, author of the book Dependency Injection in .NET, has a nice article about the injection of Primitive Dependencies.

From a technical perspective I find the part where he configures Castle Windsor to use his custom conventions most interesting. When I come across such a feature that exists in another DI container but is not present in Unity I try to port that feature. And I have yet to find some piece of functionality that cannot be implemented easily with a few lines of code. Adding support for parameter conventions takes about ~250 LoC. Due to the differences in their respective architecture the Unity implementation is two-part: The core part of the convention implements the custom interface IDependencyResolverConvention the part that performs the actual work implements IDependencyResolverPolicy which comes as part of the Unity infrastructure.

These are the interfaces:

public interface IDependencyResolverConvention
{
  bool CanCreateResolver(IBuilderContext context, DependencyInfo dependency);
  IDependencyResolverPolicy CreateResolver(IBuilderContext context, DependencyInfo dependency);
}

public interface IDependencyResolverPolicy : IBuilderPolicy
{
  object Resolve(IBuilderContext context);
}

Using that newly created infrastructure (and a second convention that works like the ConnectionStringConvention described in the article) you can resolve classes that look like these:

public class TakesPrimitiveParameter
{
  public int Abc { get; set; }
  public TakesPrimitiveParameter(int abc)
  {
    this.Abc = abc;
  }
}
public class TakesConnectionStringParameter
{
  public string AbcConnectionString { get; set; }
  public TakesConnectionStringParameter(string abcConnectionString)
  {
    this.AbcConnectionString = abcConnectionString;
  }
}

The integer value abc will be read from the appSettings section of your config file. The ConnectionString abc will be read from the connectionStrings section.

public class AppSettingsConvention : IDependencyResolverConvention
{
  public bool CanCreateResolver(IBuilderContext context, DependencyInfo dependency)
  {
    return dependency.DependencyType == typeof(int);
  }
  public IDependencyResolverPolicy CreateResolver(IBuilderContext context, DependencyInfo dependency)
  {
    return new AppSettingsResolverPolicy(dependency.DependencyName, dependency.DependencyType);
  }
}

public class AppSettingsResolverPolicy : IDependencyResolverPolicy
{
  private readonly string name;
  private readonly Type targetType;
  public AppSettingsResolverPolicy(string name, Type targetType)
  {
    this.name = name;
    this.targetType = targetType;
  }
  public object Resolve(IBuilderContext context)
  {
    string setting = ConfigurationManager.AppSettings[this.name];
    return Convert.ChangeType(setting, this.targetType);
  }
}

Setting up the registrations is as easy as this:

var container = new UnityContainer().WithDefaultConventionsForLiteralParameters();
var foo = container.Resolve<TakesPrimitiveParameter>();

Or if you prefer to have more fine granular control over the used conventions you can add them one by one:

var container = new UnityContainer()
                 .WithConventionsForLiteralParameters(
                   new ConnectionStringConvention(),
                   new AppSettingsConvention());
var foo = container.Resolve<TakesPrimitiveParameter>();

Neat and as Mark puts it: If you stick to your conventions it will just keep working when your code base grows.

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