IOC注入框架——Unity中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>

 

看到上面的內容好多人會感到怎麼這麼複雜啊?實際上,上面的內容是一個完整的結構,以供參考,在日常開發中一般不會全用到的,這裏用的最多的元素標記是:<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());

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章