在上一篇文章“Unit简单依赖注入”我们可以实现构造对象和被依赖对象之间的 松耦合,使我们的抽象层(Player)能够保持稳定,但是在并没有把客户类和Player类之间彻底解耦,即当我们不想使用MP3Player注入,而 想使用CDPlayer注入时,我们需要修改客户类的容器注册。下面我们使用web.config配置文件来解决这个问题。
Unity 应用程序块可以从 XML 配置文件中读取配置信息。配置文件可以是 Windows Forms 应用程序的 App.config 或者 ASP.NET 应用程序的 Web.config。当然,也可以从任何其他 XML 格式的文件或者其他数据源中加载配置信息。

在本文中,将研究Unity 配置文件的格式、配置的读取、通过示例说明实例的获取。
1. Unity 配置文件的完整格式

<?xml version="1.0" encoding="utf-8" ?> 
 <configuration>
 <configSections>
 <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration, Version=1.0.0.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
 </configSections><unity>
 <typeAliases>
     <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,Microsoft.Practices.Unity" />
     <typeAlias alias="external" type="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager, Microsoft.Practices.Unity" />
     <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 type="Custom.MyBaseClass" mapTo="Custom.MyConcreteClass" />
         <type type="IMyInterface" mapTo="MyRealObject" name="MyMapping" />
         <type type="Custom.MyBaseClass" mapTo="Custom.MyConcreteClass">
           <lifetime type="singleton" /> 
         </type>
         <type type="IMyInterface" mapTo="MyRealObject" name="RealObject">
           <lifetime type="external" />
         </type>
         <type type="Custom.MyBaseClass" mapTo="Custom.MyConcreteClass">
           <lifetime value="sessionKey" type="MyApplication.MyTypes.MyLifetimeManager,MyApplication.MyTypes" />
         </type>
         <type type="IMyInterface" mapTo="MyRealObject" name="CustomSession">
           <lifetime type="MyCustomLifetime" value="ReverseKey" typeConverter="MyApplication.MyTypes.MyTypeConverter,MyApplication.MyTypes" />
         </type>
         <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>
 </containers>
 </unity>
 </configuration>


结构图示:




unity配置文件在哪_游戏


看到上面的内容好多人会感到怎么这么复杂啊?实际上,上面的内容是一个完整的结构,以供参考,在日常开发中一般不会全用到的,这里用的最多的元素标记 是:<containers>中的<container>内部的<type>标记。

Unity的配置节的名称为”Unity",节处理程序的类型为 Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,它包含在程序 集 Microsoft.Practices.Unity.Configuration 中。所在应当在网站是添加该程序集的引用。

unity 的子元素包含了一个 containers 元素,containers 元素可以包含若干个 container 元素。container 元素就是每个容器的配置,它有一个可选的 name 属性,用于指定容器的名称。

<types> 元素是 container 元素的子元素之一。包含任意数量的 type元素,用以添加类型注册,这些配置被container.RegisterType<TFrom,TTo>()注册;type元素的属性。
name:在注册此类型时使用的名称。此属性是可选的,如果不指定此属性,所在的 add 元素即为默认的类型映射。
type:容器中配置的源类型。如果这是映射注册,这就是映射的起始对象的类型;如果这是单件注册,这就是对象的类型。此属性是必须的。
mapTo:类型映射的目标类型。如果这是映射注册,这就是映射的目标对象的类型。此属性是可选的。
lifetime:设置用于给定的类型和名称的生命周期。是一个来自 LifetimeStyle 枚举的值。有效的值是 Transient(默认),它导致了容器每次都创建一个新的实例;以及 Singleton,它使容器为每个请求返回同一实例。如果在配置一个单件时同时指定了 type 和 mapto 属性,SetSingleton 方法将返回指定在 mapTo 属性中的类型。如果 mapTo 属性没有指定值,SetSingleton 方法将返回指定在 type 属性中的类型。

<instances> 元素保持了用于此容器的已有对象实例的列表。这些对象被用容器的 RegisterInstance 方法进行注册。instances 元素包含了一系列添加单个实例的 add 元素。
add 元素的属性。
name:注册此实例时使用的名称。此属性是可选的。
type:此实例的类型。此属性是可选的。如果忽略,假定的类型是 System.String。
value:用于初始化实例的值。此属性是必须的。
typeConverter:用以转换提供的值到实例的匹配类型的类型转换器。如果没有指定,将使用指定类型的默认转换器。此属性是可选的。

<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>


在执行Container.Resolve()生成对象实例的时候,会根据上面的配置信息的 内容对要生成的对象进行依赖注入。

二、加载配置信息到容器中
1、加载一个单独的未命名容器或规定了默认容器:

IUnityContainer container = new UnityContainer();
 UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
 section.Containers.Default.Configure(container);


这样就会根据配置文件中的配置信息,在UnityContainer容器中注册类型映射

2、加载一个特殊命名容器的配置信息,需要使用定义在配置文件中的容器名,而不是引用默认容器。例如,如果在配 置中有一个命名为containerOne的容器,能使用如下代码初始化并加载它:

IUnityContainer container = new UnityContainer();
 UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
 section.Containers["containerOne"].Configure(container);

3、为了从配置信息中创建一个嵌套容器继承, 可以简单的使用CreateChildContainer方法在你需要的继承深度中创建容器对象,然后通过读取各自的配置文件加载合适的配置。下 面的

代码展示了如何从配置文件中实例化和加载两个容器,这个配置文件同时包含了针对两个命名为 containerOne和newstedChildContainer容器的注册信息,类型映射和扩展定义。 
 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);

三、从容器的映射信息生成对象实例:这里依然还是用UnityContainer类的Resolve方法来实现的。在此不多说了。

四、一个简单的例子:

1、类的结构:
     public abstract class Player
     {
         public abstract string Play();
     }
     public class MP3Player : Player
     {
         public override string Play()
         {
             return ("this is a MP3Player");
         }
     }
     public class CDPlayer : Player
     {
         public override string Play()
         {
             return ("this is a CDPlayer");
         }
     }
     public class DVDPlayer : Player
     {
         public override string Play()
         {
             return ("this is a DVDPlayer");
         }
     }

2、Web.Config文件的配置

<configSections>
      <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
     </configSections>
     <unity>
      <containers>
       <container>
        <types>
         <type type="Player,App_Code" mapTo="MP3Player,App_Code"></type>
        </types>
       </container>
      </containers>
     </unity>
     (车延禄)


3、客户代码的实现:
   

IUnityContainer container = new UnityContainer();
     UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
     section.Containers.Default.Configure(container);    Player p = container.Resolve<Player>();
     Response.Write(p.Play());


   
4、运行结果:


unity配置文件在哪_配置信息_02