Using Design-Time Configuration
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
- Loading Configuration File Information into a Container
- Loading the Configuration from Alternative Files
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.
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="https://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.
IUnityContainer container = new UnityContainer()
.LoadConfiguration();
'Usage
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:
IUnityContainer container = new UnityContainer()
.LoadConfiguration("otherContainerElement");
'Usage
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:
IUnityContainer container = new UnityContainer()
.LoadConfiguration(section) // Loads unnamed <container> element
.LoadConfiguration(section, "otherContainerElement"); // named <container> element
'Usage
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:
var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
IUnityContainer container = new UnityContainer();
section.Configure(container); // Unnamed <container> element
section.Configure(container, "otherContainerElement"); // named container element
'Usage
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.
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);
'Usage
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.