Using Design-Time Configuration

Microsoft Enterprise Library 5.0

DropDown image DropDownHover image Collapse image Expand image CollapseAll image ExpandAll image Copy image CopyHover image

Using Unity typically requires the configuration of a Dependency Injection (DI) container. You can configure a container by using the Unity API, a .NET configuration file, or to a limited degree by using attributes. This topic describes how to use an XML configuration file to supply the required configuration information..

Dependency injection is a very flexible pattern, and to be used successfully requires the developer to provide information to the container about his applications. The two most common configuration tasks are setting up type mappings and configuring injection of a type. Type mappings enable you to request a type from the container that results in the container returning an instance of a different type (typically a derived class or interface implementation). Configuring injection for a type entails specifying information such as which constructor gets called, which properties get injected, and what their values are. The Unity configuration schema encompasses these types of configuration and is also extensible to allow for additional kinds of configuration such as Unity interception configuration, see The Unity Configuration Schema. The following sections provide more details:

Format of the Unity Configuration File

Unity uses the System.Configuration namespace supplied with the .NET framework. This means that configuration information can be stored in any .NET configuration file, which is typically your App.config or Web.config file, but it could be stored elsewhere. The following example is a simple XML configuration file.

XML Copy Code
<configuration>

  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>

  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="ILogger" type="MyApp.ILogger, MyApp" />
    <namespace name="MyApp.Implementations" />
    <assembly name="MyApp" />
    
    <container>
      <register type="ILogger" name="special" mapTo="SpecialLogger" />    
    </container>

  </unity>

</configuration>

A Unity configuration section consists of a set of type lookup modifiers (aliases, namespaces, and assemblies), and one or more <container> elements. A <container> element has a set of <registration> elements that provide the configuration for the container's types. Other elements can also be used in the container, see The Unity Configuration Schema for a full description of the schema.

The XML namespace specified with the xmlns attribute in the example is not required at run time. However, it is useful because Visual Studio uses it to match the section with the Unity XML schema and to provide IntelliSense in the XML editor.

Loading Configuration File Information into a Container

Adding a Unity configuration section to a configuration file neither create an actual container nor configures it. You must create a Unity container instance, read the configuration file, and load the configuration file information into the container.

Note:
Alternatively, after you create the container, you can configure it programmatically at run time with registrations, type mappings, and any extensions. For more information about run-time configuration, see Run-Time Configuration.

To load the configuration file information into a container, use the LoadConfiguration extension method on IUnityContainer. This interprets the default configuration file for your application, seeks the Unity configuration section, and configures the container. The LoadConfiguration extension method has several overloads.

Unity offers a convention-based approach to configuring your container that can be applied in most cases. To take advantage of this you must use the default Unity configuration section name of unity and specify an un-named container in your App.config or Web.config file. The following example uses this approach.

C# Copy Code
IUnityContainer container = new UnityContainer()
    .LoadConfiguration();
Visual Basic Copy Code
Dim container as IUnityContainer = New UnityContainer()
container.LoadConfiguration()

The configuration for a named container can be loaded from the default configuration section by providing the name of the container to the LoadConfiguration method as shown in the following example:

C# Copy Code
IUnityContainer container = new UnityContainer()
    .LoadConfiguration("otherContainerElement");
Visual Basic Copy Code
Dim container as IUnityContainer = New UnityContainer()
container.LoadConfiguration("otherContainerElement")

If your configuration is in a different section (either with a different name or from a different file entirely), you must first load the section object through ConfigurationManager and then pass the section to the LoadConfiguration method, as shown in the following example:

C# Copy Code
IUnityContainer container = new UnityContainer()
    .LoadConfiguration(section)  // Loads unnamed <container> element
    .LoadConfiguration(section, "otherContainerElement"); // named <container> element
Visual Basic Copy Code
Dim container as IUnityContainer = New UnityContainer()
container.LoadConfiguration(section) _
    .LoadConfiguration(section, "otherContainerElement")

You can also load multiple configurations into the same container. Non-conflicting configurations will simply be added, and if there is a conflict, such as two mappings for the same type, then the last configuration added will be the one that is used. The previous example illustrates the additive feature for configuration.

There is also an API on the UnityConfigurationSection object that can be used to configure a container. Once you have obtained the section object of the ConfigurationManager, you can call its Configure method to apply configuration to a container:

C# Copy Code
var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
IUnityContainer container = new UnityContainer();
section.Configure(container); // Unnamed <container> element
section.Configure(container, "otherContainerElement"); // named container element
Visual Basic Copy Code
Dim section = DirectCast(Configurationmanager.GetSection("unity"), UnityConfigurationSection)
Dim container as IUnityContainer = new UnityContainer()
section.Configure(container)
section.Configure(container, "otherContainerElement")

In general, the LoadConfiguration extension method is preferred as it is easier to read and use.


Loading the Configuration from Alternative Files

You are not required to store your container configuration in the standard application configuration file: App.config or Web.config. However, if you do store your configuration in a different file you must use the ConfigurationManager methods to explicitly load that specific named file.


Note:
If you use a custom configuration file, instead of App.config in an executable application, you must ensure that it is available in the runtime folder of your application. If you create a custom configuration file in a Visual Studio project, open the Properties window for the file and set the Copy to Output Directory property to Copyalways.


For example, in order to load configuration information from the named configuration file, unity.config, you must first load the section, in this case UnityConfigurationSection, as shown in following code.

See ConfigurationManager.OpenMappedExeConfiguration on MSDN for more details.

C# Copy Code
using System.Configuration;
var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = "unity.config" };
System.Configuration.Configuration configuration =
    ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
var unitySection = (UnityConfigurationSection)configuration.GetSection("unity");

var container = new UnityContainer()
    .LoadConfiguration(unitySection);
Visual Basic Copy Code
Imports System.Configuration

Dim fileMap as new ExeConfigurationFileMap() With { .ExeConfigFilename = “unity.config” }
Dim configuration as System.Configuration.Configuration = _
    ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None)
Dim unitySection = DirectCast(configuration.GetSection("unity"), UnityConfigurationSection)

Dim container as IUnityContainer = new UnityContainer()
container.LoadConfiguration(unitySection)

Note:
A <container> element in the configuration file is not an instance of a UnityContainer object. It is a named set of configurations that can be applied to a container instance later and a single <container> element can be applied to multiple UnityContainer instances.
You cannot nest containers in the configuration file. All <container> elements reside at the same level within the <containers> element. You configure nested containers by creating the containers in the required hierarchy in your code and then populating them from the appropriate <container> elements. If required, you can load more than one container from the same <container> element, and you can use more than one container element in a configuration file. For information, see Using Container Hierarchies.