Dependency Frameworks and Parameterized Constructors

April 23rd, 2012 Leave a comment Go to comments

Most dependency injection frameworks support some kind of object initialization through parameterized constructors. The question is whether or not it’s a good idea to use that feature of DI frameworks.

Consider the following code:

public interface IWorker
{
    void DoWork();
}

public class Worker : IWorker
{
    private List < string> _payLoad;
    
    public Worker(IList < string> payLoad)
    {
        if (payLoad == null || payLoad.Count() == 0)
            throw new ArgumentException();
            
        _payLoad = payLoad.ToList();
    }
    
    public void DoWork()
    {
        foreach (var item in _payLoad)
        {
            // Do work
        }
    }
}

When we use a DI container such as Unity or Castle Windsor to instantiate a Worker object, we must write some specialized code to pass in the constructor parameter (payLoad in our example). The problem I see with this is that since parameterized constructors can’t be mandated through interface IWorker, the code is only guaranteed to work with the default implementation of IWorker if one is provided. That’s pretty ugly, and pretty much defeats the purpose of using a DI framework. One of the key benefits of using a DI framework is that a new “implementation” can be “injected” into code at any time by only making subtle changes to the configuration.

In most cases the code above should be refactored as below:

public interface IWorker
{
    void DoWork(IList < string> payLoad);
}

public class Worker : IWorker
{
    public void DoWork(IList < string> payLoad)
    {
        if (payLoad == null || payLoad.Count() == 0)
            throw new ArgumentException();
    
        foreach (var item in payLoad.ToList())
        {
            // Do work
        }
    }
}

The above code is not only more concise, but is also more portable. In the event when payLoad needs to be used by more than one Worker method, we can write create an explicit Initialize method to initialize the object. The code can be refactored as follows:

public interface IWorker
{
    void DoWork();
    int GetCount();
}

public class Worker : IWorker
{
    private List < string> _payLoad;
    
    public void Initialize(IList < string> payLoad)
    {
        if (payLoad == null || payLoad.Count() == 0)
            throw new ArgumentException();
    
        _payLoad = payLoad.ToList();
    }
    
    public void DoWork()
    {
        if (_payLoad == null)
            throw new InvalidOperationException();
    
        foreach (var item in _payLoad)
        {
            // Do work
        }
    }
    
    public int GetCount()
    {
        if (_payLoad == null)
            throw new InvalidOperationException();
    
        return _payLoad.Count;
    }    
    
}

There are some very specialized instances when parameterized constructors need to be used in conjunction with DI frameworks, but those should be exceptions and must be used sparingly with deliberate intent.

  1. No comments yet.
  1. No trackbacks yet.
 

Comment moderation is enabled. Your comment may take some time to appear.