Bootstrapping Unity 2.0

Unity 2.0 features a nice(r) fluent configuration – similar to StructureMap. These run time configuration and registration methods are great, but they have a draw back in that they need to be bootstrapped differently according to the runtime environment.

For example, you might want to run an WCF enabled n-tier web site in-process during development.

Or you might want to apply mocked services during controller testing.

You don’t want to have code in your bootstrapper that knows about all the possible permutations of the resolvable instances. I think the solution is to have design-time (config.file) configurable bootstrappers.

The idea is to use the default Unity Configure() method to read the required unity configuration from the application configuration file, then resolve an instance of some interface (“IUnityConfigurator”) that is then called to perform fluent registration.

Lets start with the IUnityConfigurator interface:

public interface IUnityConfigurator{
  void Configure(IUnityContainer container);
}

Create a concrete implementation of this interface that registers the required runtime components.

public class TestUnityConfigurator : IUnityConfigurator{
  public void Configure(IUnityContainer container){
    container.RegisterType<ILogger,Logger>();
  }
}

Add the unity configuration section to the application configuration file

<configSections>
  <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
           Microsoft.Practices.Unity.Configuration,
           Version=2.0.414.0, Culture=neutral,
           PublicKeyToken=31bf3856ad364e35"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <assembly name="[assembly name of IUnityContainer]"/>
    <assembly name="[assembly name of TestUnityConfigurator]"/>
    <namespace name="[namespace name of IUnityContainer]"/>
    <namespace name="[namespace name of TestUnityConfigurator]"/>
    <container>
      <register type="IUnityConfigurator" mapTo="TestUnityConfigurator"/>
    </container>
</unity>

I wrap the access to the Unity container through a think static wrapper UnityInstance. This class has a static constructor that does the heavy lifting of configuring the UnityContainer. Note how it calls LoadConfiguration() to get XML configuration and then queries for the IUnityConfigurator interface and then performs whatever fluent configuration is neccesary.

 public static class UnityInstance{
  /// The single instance for the application
  private static UnityContainer container;

  /// Static constructor - called once per appdomain
  static UnityInstance(){
    //load the types from the configuration file
    container = new UnityContainer();
    try{
      container.LoadConfiguration();
    }
    catch (ArgumentNullException ane){
      if (ane.ParamName.Equals("section", StringComparison.OrdinalIgnoreCase)){
        throw new Exception("The neccesary configuration for Unity has not been added to the application configuration file.");
      }
    }

    //if a configurator is registered, then use it
    if (container.IsRegistered<IUnityConfigurator>()){
      IUnityConfigurator configurator = container.Resolve<IUnityConfigurator>();
      configurator.Configure(container);
    }
 }

  /// Gets the current IUnityOfWork container
  public static IUnityContainer Container{ get{return container;} }
}

Using UnityInstance.Container, it is easy to access the static unity container to resolve services or set as the ServiceLocator, or in ASP.Net, the DependencyResolver.

protected void Application_Start(){
  AreaRegistration.RegisterAllAreas();
  
  //set the CSL-compliant service locator - forces the unity initialisation 
  ServiceLocator.SetLocatorProvider(()=>new UnityServiceLocator(UnityInstance.Container));           

  //now set the MVC dependency resolver
  DependencyResolver.SetResolver(new UnityDependencyResolver(UnityInstance.Container));
            
  //register filters after setting the DI container so that DI can be used in resolving filters
  RegisterGlobalFilters(GlobalFilters.Filters);

  RegisterRoutes(RouteTable.Routes);
}

Conclusion

This post has provided some ideas for the use of an injected configurator for Unity 2.0 to enable the fluent configuration of Unity.

kick it on DotNetKicks.com

About these ads
This entry was posted in Dependency Injection/Inversion of Control, Unity and tagged , , , . Bookmark the permalink.

2 Responses to Bootstrapping Unity 2.0

  1. AndyH says:

    Is that definitely supposed to be IUnityContainer in there? Or should it be “IUnityConfigurator”?

    Thx – A

    • xhalent says:

      The configuration section is correct. I’m using the web config to register IUnityConfigurators. Unity will pick these registrations automatically. In my UnityContainer, I then query the UnityContainer for each IUnityConfigurator it knows about and call the configure method.

      if (container.IsRegistered()){
      IUnityConfigurator configurator = container.Resolve();
      configurator.Configure(container);

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