skip to the main content area of this page
Patterns and Practices

 

Unity and StructureMap - Dynamically Configuring Constructor Injection via Fluent Interfaces


There is a section in the Unity Documentation, called Dynamically Configuring Constructor, Property, and Method Injection, that explains how to use the fluent API to inject dependencies into constructors, properties, and methods.

Typically you need to use the fluent API in Unity when injecting simple parameter types ( e.g. strings, integers, etc. ). For example, if I want to inject the database connection string into a Data Access Object ( DAO ):

 

public interface IProductDAO {}

 

public class ProductDAO : IProductDAO

{

    private readonly string _connectionString;

 

    public ProductDAO(string connectionString)

    {

        _connectionString = connectionString;

    }

}

 

you can inject the connection string by configuring the InjectedMembers for ProductDAO in Unity as follows:

 

IUnityContainer container = new UnityContainer();

 

container.RegisterType<IProductDAO, ProductDAO>();

 

container.Configure<InjectedMembers>()

    .ConfigureInjectionFor<ProductDAO>(

    new InjectionConstructor(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString));

 

You can do the same thing using StructureMap 2.5 using StructureMap's Fluent Interface and Registry as follows:

 

ObjectFactory.Initialize(x => x.AddRegistry(new InfrastructureRegistry()));

 

public class InfrastructureRegistry : Registry

{

    protected override void configure()

    {

            ForRequestedType<IProductDAO>()

            .TheDefault.Is.OfConcreteType<ProductDAO>()

            .WithCtorArg("connectionString").EqualTo(

            ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);

    }

}

 

This might be borderline nitpicking, but with Unity you need to specify every parameter that is injected into the constuctor when using the API. For constructors with a lot of parameters this is a bit of an inconvenience. If we add an ILogger to the list of constructor parameters of ProductDAO, we need to add it via the fluent API even though we have already added it to the container.

Here is our new ProductDAO:

 

public class ProductDAO : IProductDAO

{

    private readonly string _connectionString;

    private readonly ILogger _logger;

 

    public ProductDAO(string connectionString, ILogger logger)

    {

        _connectionString = connectionString;

        _logger = logger;

    }

}

 

Here we are using Unity:

 

IUnityContainer container = new UnityContainer();

 

container.RegisterType<ILogger, Logger>();

container.RegisterType<IProductDAO, ProductDAO>();

 

container.Configure<InjectedMembers>()

    .ConfigureInjectionFor<ProductDAO>(

    new InjectionConstructor(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString,

        typeof(ILogger)));

 

Notice how I need to still specify ILogger via the Unity Fluent API ( typeof(ILogger) ) as well as add the Logger to the UnityContainer.

Using StructureMap, StructureMap will just pull the ILogger from the container and you don't need to add it via the Fluent API as well:

 

public class InfrastructureRegistry : Registry

{

    protected override void configure()

    {

        ForRequestedType<ILogger>().TheDefaultIsConcreteType<Logger>();

 

        ForRequestedType<IProductDAO>()

        .TheDefault.Is.OfConcreteType<ProductDAO>()

        .WithCtorArg("connectionString").EqualTo(

        ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);

    }

}

 

Again, this only becomes an inconvenience when you need to use the Fluent API with Unity and you have a lot of constructor parameters.

 

Unity Webcasts

 

StructureMap Tutorials


Tags: DependencyInjection, IoC, StructureMap, Unity


Topics



 

Popular Tags



Recent Links