Configuring StructureMap using web.config

For the project I am currently working on I chose StructureMap as the dependency injection framework.  The configuration for StructureMap is pretty easy – in my case it looked something like this.

public static void ConfigureStructureMap()
{
    ObjectFactory.Initialize(x =>
    {
        x.ForRequestedType<IAuthenticationService>().TheDefaultIsConcreteType<AuthenticationService>();
        x.ForRequestedType<ILdapAuthenticationService>().TheDefaultIsConcreteType<LdapAuthenticationService>();
        x.ForRequestedType<ICrmService>().TheDefaultIsConcreteType<CrmService>();
        x.ForRequestedType<IOneTimePinService>().TheDefaultIsConcreteType<OneTimePinService>();

        x.ForRequestedType<IUserRepository>().TheDefaultIsConcreteType<UserRepository>();

        x.ForRequestedType<IThreadFactory>().TheDefaultIsConcreteType<ThreadFactory>();
    });
}

Pretty cool – you just specify all the the interfaces and the corresponding concrete types.  StructureMap also allows you to do loads of extra configuration options, but in my case this is what I will be using 99% of the time.

Move the configuration to the web.config

Because some of the services invoke webservices which are unavailable to me during development I swapped some of the concrete implementations for mock services.  Because I didn’t really want to change the code to allow this change I decided to move the configuration into the web.config file.  I found the StructureMap documentation a little confusing at some point – I simply couldn’t find a proper example of how to configure a few simple classes as the default concrete types.  So hopefully this post will serve as an example.

Firstly, add the following tag inside the tag.

<section name="StructureMap" type="StructureMap.Configuration.StructureMapConfigurationSection,StructureMap"/>

Now you need to tell StructureMap to read all the settings from the config file.

public static void ConfigureStructureMap()
{
    ObjectFactory.Initialize(x =>
    {
        x.PullConfigurationFromAppConfig = true;
    });
}

And now you can add all your StructureMap settings – you can do this anywhere inside the tag.  Again, my example here is the simplest case – I simply want to define the concrete classes for a bunch of interfaces.

<StructureMap>
  <Assembly Name="ProjectName.Server" />

  <PluginFamily Type="ProjectName.Server.Services.IAuthenticationService" Assembly="ProjectName.Server" DefaultKey="Default">
    <Plugin Type="ProjectName.Server.Services.Mocks.MockAuthenticationService" Assembly="ProjectName.Server" ConcreteKey="Default" />
    <!--Plugin Type="ProjectName.Server.Services.AuthenticationService" Assembly="ProjectName.Server" ConcreteKey="Default" /-->
  </PluginFamily>
  <PluginFamily Type="ProjectName.Server.Services.ILdapAuthenticationService" Assembly="ProjectName.Server" DefaultKey="Default">
    <Plugin Type="ProjectName.Server.Services.LdapAuthenticationService" Assembly="ProjectName.Server" ConcreteKey="Default" />
  </PluginFamily>
  <PluginFamily Type="ProjectName.Server.Services.ICrmService" Assembly="ProjectName.Server" DefaultKey="Default">
    <Plugin Type="ProjectName.Server.Services.CrmService" Assembly="ProjectName.Server" ConcreteKey="Default" />
  </PluginFamily>
  <PluginFamily Type="ProjectName.Server.Services.IOneTimePinService" Assembly="ProjectName.Server" DefaultKey="Default">
    <Plugin Type="ProjectName.Server.Services.OneTimePinService" Assembly="ProjectName.Server" ConcreteKey="Default" />
  </PluginFamily>
  <PluginFamily Type="ProjectName.Server.Data.Repositories.IUserRepository" Assembly="ProjectName.Server" DefaultKey="Default">
    <Plugin Type="ProjectName.Server.Data.Repositories.UserRepository" Assembly="ProjectName.Server" ConcreteKey="Default" />
  </PluginFamily>
  <PluginFamily Type="ProjectName.Server.Tools.IThreadFactory" Assembly="ProjectName.Server" DefaultKey="Default">
    <Plugin Type="ProjectName.Server.Tools.ThreadFactory" Assembly="ProjectName.Server" ConcreteKey="Default" />
  </PluginFamily>
</StructureMap>

Hopefully this will save someone some time.  Happy coding.