The simplest form of configurable Dependency Injection


I love the concept of dependency injection, but I’ve never found a dependency injection framework that I think is easy enough to use.

They either rely on XML configurations that are really awkward.
Others have force you to resolve objects by some untyped string ID.

I don’t want that.
I want to resolve my objects through normal methods, that’s intuitive and the code becomes readable too.

However, if you try to accomplish this by code without writing yet another framework.
You will either have to decide if you want your resolver to have static or instance methods.

If you go for instance methods, then you will have to make some sort of factory for the factory itself if you want to be able to return other implementations of the same factory.

If you go for static methods, you will probably end up with a static dead factory that you can’t change in run-time, since that’s the nature of static methods.

I personally like the simplicity of the static methods, but as I said, they are not configurable.

But there is a quite slick solution to this problem;
I have started to use static delegates for this instead.

By exposing static delegates I can get the same simplicity as when calling static methods, but
at the same time achive the pluggability of instance methods (or rather of different implementations of the same factory).

Here is some sample code:


//The Class that you use to get your objects
public static class Config
{
    public static Func<IDbConnection> GetConnection = 
      DefaultConfig.GetConnection;

     public static Func<IDbCommand> GetCommand = 
      DefaultConfig.GetCommand;
}

//Default implementations of the config functions
public static class DefaultConfig
{

  //Configure a connection
  public static IDbConnection GetConnection()
  {
       return new SqlConnection("myconnstr");
  }

  //Configure a command
  public static IDbCommand GetCommand()
  {
      IDbCommand cmd = new SqlCommand();
    
      //Inject connection into command
      //Any sort of injection is possible here, ctor, prop, method etc.
      cmd.Connection = Config.GetConnection();

      return cmd;
  }
}

Look at the “Config” class above, it exposes “Func of IDbConnection”, meaning it will return a delegate that in turn returns a DbConnection once invoked.
This allows me to assign new implementations to that static field if I want to, and thus make all consumers of that delegate get objects according to my new implementation.

My code can then consume the factory like this:

IDbCommand cmd = Config.GetCommand();

That looks quite OK, doesn’t it?

And in order to change the implementation for some resolve method:

Config.GetCommand = () => new MySpecialCommand();

Or if you like the old delegate syntax:

Config.GetCommand = delegate
                    {
                        return new MySpecialCommand();
                    };

I use this all the time now, I simply change the config implementation for my unit tests and use the default implementation when running the real applications.

//Roger

13 thoughts on “The simplest form of configurable Dependency Injection

  1. Acctually, I wouldn’t call this Dependency Injection since you’re not injecting the dependency. This is a different form of Inversion of Control than Martin Fowler’s definition of Dependency Injection.

    You might want to take a look at Jeremy Miller’s newer versions of StructureMap. Pretty nice syntax.

    But it’s still too complex for my taste. I prefer using context based dependency injection that can be used for application decoupling and not just for tests. But that puts high demands on the entire application architecture.

    So I like this alternative when you really only need an easy way to do decouple a legacy class for testability purposes.

    (Vi ses i augusti. :) )

  2. Hi.

    No, you are assuming that I reffer to the consumer code calling out for its dependency, which would be service locator pattern.

    If you look at the DefaultConfig.GetCommand, you can use DI inside such method, and invoke the definitions of other objects from there, eg, getting a connection and injecting it into the command.
    So you do DI isnide those object configurations, just the same way as you would do DI with a framework.

    The consumer of a DI framework is always relying on service locator in order to get the configured objects out of the context.

    That is, you need to tell a DI framework to _give_ you a configured object.

    And you can do complete decoupling of an application with this, the dependency you get with the static factory is not tighter than the dependency you get to any other DI framework (unless you use some sort of abstraction layer for that)

    eg. using spring you get something like “var context = ApplicationContext.Configure()”, that is just as static and tightly coupled as any static factory.

    So lets say you would want to get an order repository configured for NHibernate out of spring, you would do something like:

    IOrderRepository repo = context.GetObject[IOrderRepository]();

    and in my case;

    IOrderRepository repo = Config.GetOrderRepository();

    • I would still argue that even though your pattern doesn’t necessarily exclude dependency injection. It doesn’t use DI at all. That’s why the title is confusing to me.

      In your sample DefaultConfig.GetCommand doesn’t use DI. You could use it there, but you’re currently using a service locator there as well.

      I’m not saying that the pattern is wrong or that it’s worse than common DI frameworks.

      In fact, this exact pattern is very common in dynamic languages for testing purposed. Every method is overridable so you have a default that is then overridden during tests.

      I’m just saying, you don’t have anything in there that is doing Dependency Injection. So, the term is misplaced to describe the pattern. It’s IoC but not (necessarily) DI.

      My issue with this pattern is that the application architecture is designed around a default implementation. That could potentially lead the design process to leak across layers.

      But, then I have an issue with DI frameworks and global dependency configuration in general but that’s a different story.

      You can’t have two different instances of Config in the same app domain for example. That’s makes all your consumers single purpose. I would have Config be a contextualized configuration object that is passed through injection to consumers.

      • The first Config object would be instantiated in Main() or Application_Start() or where ever the application is first started. There by eliminating the need for a service locator at all.

        For tests I would instantiate a mock or fake Config object in the context where it is needed.

      • >>I’m just saying, you don’t have anything in there that is doing Dependency Injection. So, the term is misplaced to describe the pattern. It’s IoC but not (necessarily) DI.

        That is simply not correct.

        The definition of Service location is when a component resolves it’s own dependencies (through the help of the locator).
        eg. if the SqlCommand class would ask for it’s own dependencies.

        This is not the case here, the SqlCommand class can only by configured through dependency injection.

        So injecting a connection from the outside into the command object _is_ dependency injection, and that is exactly what is happening inside the GetCommand method.

        The config method “GetCommand” ofcourse uses service location to resolve the objects that will be injected into the subject of the configuration (eg. the command object)

        This is exactly how it is implemented in DI frameworks also, the DI framework first needs to resolve the dependencies, and then inject them into the subject.

        Regarding one config per app domain:
        This is true, but I have yet to see a real world case where you need to be able to have multiple implementations of the same configuration in the same application.
        Maybe there is some special case where it is needed, but by all means, use the right tools for the right task.

        I’ve used the same argument when I built NAspect, that we support different AOP configurations in the same app domain.
        But I have never needed that either, so it is a somewhat constructed argument/problem.

      • >> So injecting a connection from the outside into the command object _is_ dependency injection, and that is exactly what is happening inside the GetCommand method.

        I see what you mean. I was focusing on the consumer of the Config factory. Which is NOT using dependency injection. But, yea the sample implementation is using DI. And that’s your point.

        What is confusing is that this pattern is really about the resolver. Only the implementation is using DI. Some test implementation may create a IDbCommand that isn’t using a connection. You could easily strip this pattern of DI. You could also do all this DI stuff even without the resolver.

        So I would still argue that this article is about a locator/resolver and not DI per say. But since you’re doing it specifically as a means to later do DI it’s related. Got ya.

        >> But I have never needed that either, so it is a somewhat constructed argument/problem.

        Well, you don’t “need” it. But if you do this, you open up your application for new design possibilities that could change your overall architecture.

        But my experience has been that legacy frameworks haven’t considered IoC in the API design which sometimes makes it difficult to use.

        However, if you have frameworks that will allow you to utilize this concept through out, it can be very powerful. I can show you some examples later.

        Of course, this isn’t as useful on simple applications where you may over engineer your infrastructure code.

        >> use the right tools for the right task

        !

  3. If I understand correctly you’re abstracting an IoC container of your choice so that in certain scenarios (unit testing) you can resolve by some simpler means rather than configuring the IoC container.

    Personally I’m not too keen on this as it involves writing an abstracting layer (static Config class) and this means more code. Is the issue rather that the IoC container of your choice is a real pain to easily configure for writing unit tests? Maybe consider one that can be easily configured in code like Bloom on codeplex (note: I wrote it) or Autofac.

  4. Pingback: DotNetShoutout
  5. A while back, I was in the same boat that you’re. Doing all of that XML config for DI was scary, and indeed it is. Further, I didn’t want to use strings all over the place because they didn’t provide me with compile-time safety which made refactoring difficult. Then I stumbled upon Autofac. It was designed to address these two exact problems in a very elegant way. I’ve kicked around a number of other DI frameworks, but this one fit me the best.

  6. Roger,

    For the sake of the argument, you do not need a hard dependency on a single DI framework, you can build your code to use the common service locator

    http://www.codeplex.com/CommonServiceLocator

    which is a cooperation between MS and the DI community (initiative taken by Ayende).

    Also there are plenty of frameworks that doesnt require xml configuration.. for example autofac.. you can even use Modules spread across assemblies if you want

    Daniel Cazzulino created Funq http://www.clariusconsulting.net/blogs/kzu/archive/2009/01/30/116274.aspx

    Most of them lets you do non xml/magic string resolving

  7. @Jonathan and Andreas:

    Yes I’m aware of Autofac, but it actually brings me very little extra compared to the lines of code above.

    It does bring some extra object activation features, eg if some object should be singleton or if it should be unique for an entire object graph.

    But except for that, I can do pretty much everything with the code above w/o the need for an external framework.

    And as the title implies, it is the “simplest form” not the “best” or “most flexible”.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s