Share via


Configuring Containers at Design Time

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

The latest Unity Application Block information can be found at the Unity Application Block site.

The following sections of this topic describe the configuration of the Unity Application Block at design time in more detail:

  • Format of the Unity Configuration File
  • Loading Configuration Information into a Container
  • Using Alternative Configuration Sources

Format of the Unity Configuration File

The following XML example code shows the outline schema of the configuration file. You must edit this file using a text editor, such as the XML editor included in Visual Studio, in order to provide configuration information for the application block. The configuration file typically belongs to an application and contains multiple configuration sections, one of which can be a Unity configuration section.

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

For more information about each element and attribute that you can use in the configuration file for the Unity Application Block configuration, see Source Schema for the Unity Application Block and Unity Configuration Schematic.

<?xml version="1.0" encoding="utf-8" ?> 
<configuration>

<configSections>
  <section name="unity"
            type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
                 Microsoft.Practices.Unity.Configuration, =1.2.0.0,
                 Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>

<unity>

  <typeAliases>

    <!-- Lifetime manager types -->
    <typeAlias alias="singleton"
         type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,
               Microsoft.Practices.Unity" />
    <typeAlias alias="perThread"
         type="Microsoft.Practices.Unity.PerThreadLifetimeManager,
               Microsoft.Practices.Unity" />
    <typeAlias alias="external"
         type="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager,
               Microsoft.Practices.Unity" />

    <!-- User-defined type aliases -->
    <typeAlias alias="IMyInterface"
         type="MyApplication.MyTypes.MyInterface, MyApplication.MyTypes" />
    <typeAlias alias="MyRealObject" 
         type="MyApplication.MyTypes.MyRealObject, MyApplication.MyTypes" />
    <typeAlias alias="IMyService"
         type="MyApplication.MyTypes.MyService, MyApplication.MyTypes" />
    <typeAlias alias="MyDataService"
         type="MyApplication.MyTypes.MyDataService, MyApplication.MyTypes" />
    <typeAlias alias="MyCustomLifetime" 
         type="MyApplication.MyLifetimeManager, MyApplication.MyTypes" />

  </typeAliases>

  <containers>

    <container name="containerOne">

      <types>

        <!-- Type mapping with no lifetime — defaults to "transient" -->  
        <type type="Custom.MyBaseClass" mapTo="Custom.MyConcreteClass" />

        <!-- Type mapping using aliases defined above -->  
        <type type="IMyInterface" mapTo="MyRealObject" name="MyMapping" />

        <!-- Lifetime managers specified using the type aliases -->
        <type type="Custom.MyBaseClass" mapTo="Custom.MyConcreteClass">
          <lifetime type="singleton" /> 
        </type>
        <type type="IMyInterface" mapTo="MyRealObject" name="RealObject">
          <lifetime type="perThread" />
        </type>
        <type type="IMyInterface" mapTo="MyRealObject" name="RealObject">
          <lifetime type="external" />
        </type>

        <!-- Lifetime manager specified using the full type name -->
        <!-- Any initialization data specified for the lifetime manager -->
        <!-- will be converted using the default type converter -->
        <type type="Custom.MyBaseClass" mapTo="Custom.MyConcreteClass">
          <lifetime value="sessionKey"
                    type="MyApplication.MyTypes.MyLifetimeManager,
                          MyApplication.MyTypes" />
        </type>

        <!-- Lifetime manager initialization using a custom TypeConverter -->
        <type type="IMyInterface" mapTo="MyRealObject" name="CustomSession">
          <lifetime type="MyCustomLifetime" value="ReverseKey"
                    typeConverter="MyApplication.MyTypes.MyTypeConverter,
                                   MyApplication.MyTypes" />
        </type>

        <!-- Object with injection parameters defined in configuration -->
        <!-- Type mapping using aliases defined above -->  
        <type type="IMyService" mapTo="MyDataService" name="DataService">
          <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement,
                                     Microsoft.Practices.Unity.Configuration">
            <constructor>
              <param name="connectionString" parameterType="string">
                <value value="AdventureWorks"/>
              </param>
              <param name="logger" parameterType="ILogger">
                <dependency />
              </param>
            </constructor> 
            <property name="Logger" propertyType="ILogger" />
            <method name="Initialize">
              <param name="connectionString" parameterType="string">
                <value value="contoso"/>
              </param>
              <param name="dataService" parameterType="IMyService">
                <dependency />
              </param>
            </method>
          </typeConfig>
        </type>

      </types>

      <instances>
        <add name="MyInstance1" type="System.String" value="Some value" />
        <add name="MyInstance2" type="System.DateTime" value="2008-02-05T17:50:00"  />
      </instances>

      <extensions>
        <add type="MyApp.MyExtensions.SpecialOne" />
      </extensions>

      <extensionConfig>
        <add name="MyExtensionConfigHandler"
             type="MyApp.MyExtensions.SpecialOne.ConfigHandler" />
      </extensionConfig>

    </container>

    <!-- ... more containers here ... -->

  </containers>

</unity>

</configuration>

Loading Configuration Information into a Container

The Unity Application Block does not automatically read the configuration information or create and prepare containers. You must programmatically instantiate a Unity container in your application. You can programmatically configure it with registrations, type mappings, and any extensions or you can configure it by reading configuration information from a file.

If the configuration defines an unnamed container, that unnamed container is the default container. You can also declare named containers in addition to the default, unnamed container. By using Unity, you can load the information from each container configuration section into containers that you have already created as part of a container hierarchy.

Note

You can load the configuration information for the default container by specifying the default container as follows:
section.Containers.Default .Configure(myContainer)

The following example code will instantiate a new Unity container and then load it with the registrations, type mappings, and extensions defined in the configuration file for that container.

IUnityContainer container = new UnityContainer();
UnityConfigurationSection section
  = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers.Default.Configure(container);
'Usage
Dim container As IUnityContainer = New UnityContainer()
Dim section As UnityConfigurationSection _
  = CType(ConfigurationManager.GetSection("unity"), UnityConfigurationSection)
section.Containers.Default.Configure(container)

To load the configuration information for a specific named container, you use the container name defined in the configuration instead of referencing the default container. For example, if you have a container defined in the configuration with the name containerOne, you can instantiate and load it using the following code.

IUnityContainer container = new UnityContainer();
UnityConfigurationSection section 
  = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers["containerOne"].Configure(container);
'Usage
Dim container As IUnityContainer = New UnityContainer()
Dim section As UnityConfigurationSection _
  = CType(ConfigurationManager.GetSection("unity"), UnityConfigurationSection)
section.Containers("containerOne").Configure(container)

To create a hierarchy of nested containers from configuration information, you simply create the containers in the required hierarchy using the CreateChildContainer method and then load each one with the appropriate container information. The following code shows an example of instantiating and loading two containers from a configuration file that contains registrations, type mappings, and extensions for two containers named containerOne and nestedChildContainer.

IUnityContainer parentContainer = new UnityContainer();
IUnityContainer childContainer = parentContainer.CreateChildContainer();
UnityConfigurationSection section 
  = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers["containerOne"].GetConfigCommand().Configure(parentContainer);
section.Containers["nestedChildContainer"].Configure(childContainer); 
'Usage
Dim parentContainer As IUnityContainer = New UnityContainer()
Dim childContainer As IUnityContainer =  parentContainer.CreateChildContainer()
Dim section As UnityConfigurationSection _
  = CType(ConfigurationManager.GetSection("unity"), UnityConfigurationSection)
section.Containers("containerOne").GetConfigCommand().Configure(parentContainer)
section.Containers("nestedChildContainer").Configure(childContainer) 

Note

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.

Using Alternative Configuration Sources

You can also use any XML configuration file or other source of configuration information if required. For example, you can load configuration information into containers from a specific named configuration file by using the .NET Framework System.Configuration.Configuration class to retrieve the information from any XML formatted file. The following code shows how you can read configuration information from a file named MyConfig.config.

ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = "MyConfig.config";
System.Configuration.Configuration config 
  = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None); 
UnityConfigurationSection section
  = (UnityConfigurationSection)config.GetSection("unity");
IUnityContainer container = new UnityContainer();
section.Containers["myContainer"].Configure(container);
'Usage
Dim map As New ExeConfigurationFileMap()
map.ExeConfigFilename = "MyConfig.config"
Dim config As System.Configuration.Configuration _
  = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None) 
Dim section As UnityConfigurationSection _
  = CType(ConfigurationManager.GetSection("unity"), UnityConfigurationSection)
Dim container As IUnityContainer = New UnityContainer()
section.Containers("myContainer").Configure(container)