程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 使用Unity(二):配置Unity 、讀取配置信息和獲取對象

使用Unity(二):配置Unity 、讀取配置信息和獲取對象

編輯:關於.NET

和 Enterprise Library 的其他應用程序塊一樣,Unity 的行為也可以通過配置來指定。

Unity 應用程序塊可以從 XML 配置文件中讀取配置信息。配置文件可以是 Windows Forms 應用程序的 App.config 或者 ASP.NET 應用程序的 Web.config。當然,也可以從任何其他 XML 格式的文件或者其他數據源中加載配置信息。

在本文中,將和大家一起來學習 Unity 配置文件的格式、配置的讀取、通過示例說明實例的獲取。

1. Unity 配置文件的格式

Unity 配置文件看起來像下面這樣:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <configSections>
  <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration" />
 </configSections>
 <unity>
  <containers >
   <container name="containerOne" >
    <types>
     <type type="System.Data.IDbConnection,System.Data"
         mapTo="DorianDeng.UnityConfigurationExe.MyDefaultConnection,DorianDeng.UnityConfigurationExe" />
     <type name="baseMap" type="System.Data.Common.DbConnection,System.Data"
         mapTo="DorianDeng.UnityConfigurationExe.MyDbConnection,DorianDeng.UnityConfigurationExe" lifetime="Transient" />
     <type name="interfaceSingleton" type="System.Data.IDbConnection,System.Data"
         mapTo="DorianDeng.UnityConfigurationExe.MyDbConnection,DorianDeng.UnityConfigurationExe" lifetime="Singleton"/>
    </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>
   </container>
  </containers>
 </unity>
</configuration>

1.1 配置節

Unity 的配置節的名稱為”unity",節處理程序的類型為 Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,它包含在程序集 Microsoft.Practices.Unity.Configuration 中。

1.2 unity 的子元素

unity 的子元素包含了一個 containers 元素,此元素有一個必須的屬性 Default (此屬性在目前的版本中不可用),它用於指定在不指定容器獲取容器的配置時的默認容器。

containers 元素可以包含若干個 container 元素。container 元素就是每個容器的配置,它有一個可選的 name 屬性,用於指定容器的名稱。

container 元素有下列子元素:

types 元素

instances 元素

extensions 元素

注意:不能嵌套定義容器,即 container 元素不能嵌套。

1.3 types 元素

types 元素是 container 元素的子元素之一。包含任意數量的 type元素,用以添加類型注冊。

下面的表格列出了用於 types 的 type元素的屬性。

屬性 描述 name 在注冊此類型時使用的名稱。此屬性是可選的,如果不指定此屬性,所在的 add 元素即為默認的類型映射。 type 容器中配置的源類型。如果這是映射注冊,這就是映射的起始對象的類型;如果這是單件注冊,這就是對象的類型。此屬性是必須的。 mapTo 類型映射的目標類型。如果這是映射注冊,這就是映射的目標對象的類型。此屬性是可選的。 lifetime 設置用於給定的類型和名稱的生命周期。是一個來自 LifetimeStyle 枚舉的值。有效的值是 Transient(默認),它導致了容器每次都創建一個新的實例;以及 Singleton,它使容器為每個請求返回同一實例。如果在配置一個單件時同時指定了 type 和 mapto 屬性,SetSingleton 方法將返回指定在 mapTo 屬性中的類型。如果 mapTo 屬性沒有指定值,SetSingleton 方法將返回指定在 type 屬性中的類型。

在此的單件(Singleton)即是人們常說的單件模式中的單件。SetSingleton 方法是容器提供的用於獲取單件的方法。容器會根據 lifetime 屬性來決定生成實例的方式。

1.4 instances 子元素

instances 元素保持了用於此容器的已有對象實例的列表。這些對象(包括簡單類型如數據庫連接字符串)被用容器的 RegisterInstance 方法進行注冊。instances 元素包含了一系列添加單個實例的 add 元素。

下面的表格列出了用於用於實例的 add 元素的屬性。

屬性 描述 name 注冊此實例時使用的名稱。此屬性是可選的。 type 此實例的類型。此屬性是可選的。如果忽略,假定的類型是 System.String。 value 用於初始化實例的值。此屬性是必須的。 typeConverter 用以轉換提供的值到實例的匹配類型的類型轉換器。如果沒有指定,將使用指定類型的默認轉換器。此屬性是可選的。

1.5 extensions 元素

extensions 元素保持了添加注冊到 Unity 容器的擴展的列表。extensions 包含一系列添加單個擴展的 add 元素。

下面的表格列出了用於用於擴展的 add 元素的屬性。

屬性 描述 type 添加到容器的擴展的類型。此屬性是必須的。

2 示例

我們現在僅對 types 子元素和 instances 子元素進行學習,extensions 子元素在隨後單獨進行。

在示例中,我們分別定義了二個繼承自 System.Data.Common.DbConnection 類的 MyDefaultConnection 和 MyDbConnection,雖然這二個類並不能實現真正的連接,但在此做為示例已足夠了。

2.1 讀取配置創建容器

如文章開頭配置文件中,我們定義了一個命名的窗口 "containerOne",因此,我們可以用下列代碼來讀取配置並用配置來初始化容器。

注意:Unity 應用程序塊不會自動的讀取配置信息,或者創建和准備容器。

/// <summary>
/// 創建容器。
/// </summary>
/// <returns></returns>
private static IUnityContainer CreateContainer() {
  IUnityContainer container = new UnityContainer();
  UnityConfigurationSection section
   = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
  section.Containers["containerOne"].GetConfigCommand().Configure(container);
  return container;
}

在上面的代碼中,我們用第一行來實例化一個容器,第二行使用 .NET 的 ConfigurationManager 類來讀取配置節,第三行初始化容器。

如果我們定義了一個默認的容器(未命名的容器),那麼,我們就可以用下列的代碼來初始化容器:

section.Containers.Default.GetConfigCommand().Configure(container);

嵌套的容器為管理依賴注入和對象生命周期提供了有用的功能,這在以後的文章中會詳細討論。

雖然,在配置文件中我們並不能嵌套的定義容器,但可以使用代碼來創建並初始化容器,如下面的代碼所示:

IUnityContainer parentContainer = new UnityContainer();
IUnityContainer childContainer = parentContainer.CreateChildContainer();
UnityConfigurationSection section
 = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers["containerOne"].GetConfigCommand().Configure(parentContainer);
section.Containers["nestedChildContainer"].GetConfigCommand().Configure(childContainer);

2.2 創建默認實例

默認實例就是通過未命名的類型映射來注冊的實例,如示例配置文件中的第一個 type。那麼,我們就可以使用如下代碼來獲取並使用實例。(完整的代碼請參見源文件。)

private static void DefaultMap() {
  IUnityContainer container = CreateContainer();
  IDbConnection connection = container.Get<IDbConnection>();
  connection.Open();
  connection.Close();
}

執行的效果如下圖如示:

2.3 根據鍵和類型來獲取對象

對於配置文件中的第二個 type 元素,我們可以用以下語句來獲取對象:

DbConnection connection = container.Get<DbConnection>("baseMap");

2.4 獲取單件對象

對於單件(Singleton)的相關概念,大家可以參考設計模式中的模式,在此僅討論如何用 Unity 來獲取單件對象。

在配置文件中的第三個 type 就是單件對象的配置(lifetime="Singleton")。通過下面的代碼,我們可以看到 Unity 是否實現了單件對象的獲取。

/// <summary>
/// 獲取單件對象。
/// </summary>
private static void SingletonMap() {
  IUnityContainer container = CreateContainer();
  IDbConnection connection = container.Get<IDbConnection>("interfaceSingleton");
  connection.ConnectionString = "server=10.99.123.22,...";
  Console.WriteLine(connection.ConnectionString);
  IDbConnection secodeConnection = container.Get<IDbConnection>("interfaceSingleton");
  secodeConnection.ConnectionString = "server=192.168.0.2...";
  Console.WriteLine(connection.ConnectionString);
}

效果如下圖所示:

由此我們可以看到,雖然獲取了二個對象,但事實上通過配置指定, Unity 容器為我們管理了一個單件對象,二個變量實質指向相同的對象引用。

2.5 instances 實例

在配置文件中的 instances 元素的作用相當於使用 Unity 的 RegisterSingleton 方法來注冊已有的單件對象。因此,可以使用如下代碼來獲取配置文件中的定義的二個實例:

/// <summary>
/// instances 元素的示例。
/// </summary>
private static void InstancesExample() {
  IUnityContainer container = CreateContainer();
  string instances1 = container.Get<string>("MyInstance1");
  Console.WriteLine(instances1);
  DateTime instances2 = container.Get<DateTime>("MyInstance2");
  Console.WriteLine(instances2);
}

可以看出,這與前幾個示例的獲取代碼沒有什麼區別,所以無論使用哪種方式進行配置,對客戶代碼來說都是一樣的。

3 結束語

因為目前 Unity 還僅是 CTP 版本,所以代碼、文檔都些 bug 的存在,所以文章的內容可能會與文檔的內容不一致,但這是目前正確的使用方法。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved