今天繼續介紹Unity,在上一篇的文章中,我介紹了使用UnityContainer來註冊對象之間的關係、註冊已存在的對象之間的關係,同時着重介紹
了Unity內置的各種生命週期管理器的使用方法,今天則主要介紹Unity的Register和Resolve的一些高級應用。
本篇文章將主要介紹:
1、註冊類型同時初始化構造函數參數並重載調用。
2、註冊類型同時初始化屬性參數並重載調用。
3、延遲獲取對象。
4、檢索檢索容器中註冊信息。
一、註冊類型同時初始化構造函數參數並重載調用
我們在使用Unity中註冊對象之間的關係時,可能對象有相應的構造函數,構造函數中需要傳遞相應的參數,Unity就支持這樣的註冊,其主要靠InjectionConstructor這個類來完成,我們首先來看下具體的類構造函數:
1
|
public
YourClass(
string
test, MyClass my)
|
3
|
Console.WriteLine(test);
|
4
|
Console.WriteLine(my.ToString());
|
這個構造函數有2個參數,一個字符串和一個MyClass類對象,相應的可以使用如下代碼進行註冊:
3
|
container.RegisterType<IClass, YourClass>(
|
4
|
new
InjectionConstructor(
"a"
,
new
MyClass()));
|
5
|
Console.WriteLine(
"-----------默認調用輸出-------------"
);
|
6
|
container.Resolve<IClass>();
|
這樣既可完成對象註冊的同時對構造函數參數進行注入,此時還有另外一個需求,就是雖然在註冊的時候已經對構造函數參數進行了初始化,但是在調用的時候我們想更換原先註冊的值,這時應該怎麼辦?
在Unity中,已經幫我們解決了這個問題,我們可以通過ParameterOverride和ParameterOverrides來實現,其中
ParameterOverride是針對一個參數,而ParameterOverrides是針對參數列表,有關注冊參數初始化及參數重載的全部代碼如
下:
01
|
public
static
void
ResolveParameter()
|
05
|
container.RegisterType<IClass, YourClass>(
|
06
|
new
InjectionConstructor(
"a"
,
new
MyClass()));
|
07
|
Console.WriteLine(
"-----------默認調用輸出-------------"
);
|
08
|
container.Resolve<IClass>();
|
10
|
Console.WriteLine(
"-----------重載後調用輸出-------------"
);
|
15
|
container.Resolve<IClass>(
new
ParameterOverrides()
|
18
|
{
"my"
,
new
MyClass()}
|
19
|
}.OnType<YourClass>());
|
其中需要注意的是:
1、在使用ParameterOverride方法來重載參數時,如果註冊的參數是一個具體的對象就需要使用OnType這個擴展方法來指定對應的類型,否則會報錯。
2、在使用ParameterOverrides進行重載參數時,可以使用如上面代碼的方式進行指定,但是同樣需要使用OnType來指定,不過這個的OnType指定的類型是註冊的對象類型。
效果圖如下:
可以看出,其中第一個字符串參數在重載後調用時已經發生了更改。
二、註冊類型同時初始化屬性並重載調用
這個初始化屬性和上面的初始化參數很類似,只不過不同的是,屬性的註冊初始化是使用InjectionProperty,而重載屬性是使用的
PropertyOverride和PropertyOverrides,其使用方法也是相同的,這邊就不多介紹了,代碼如下:
01
|
public
static
void
ResolveProperty()
|
04
|
container.RegisterType<IClass, MyClass>(
|
05
|
new
InjectionProperty(
"Name"
,
"A班"
),
|
06
|
new
InjectionProperty(
"Description"
,
"A班的描述"
));
|
07
|
Console.WriteLine(
"-----------默認調用輸出-------------"
);
|
08
|
Console.WriteLine(container.Resolve<IClass>().Name);
|
09
|
Console.WriteLine(container.Resolve<IClass>().Description);
|
10
|
Console.WriteLine(
"-----------重載後調用輸出-------------"
);
|
14
|
var myClass = container.Resolve<IClass>(
new
PropertyOverrides()
|
16
|
{
"Name"
,
"重載後的A班"
},
|
17
|
{
"Description"
,
"重載後的A班的描述"
}
|
20
|
Console.WriteLine(myClass.Name);
|
21
|
Console.WriteLine(myClass.Description);
|
效果圖如下:
可以看到2個屬性都已經被重載了。
Unity還爲我們提供了一個DependencyOverride重載,其使用方法和參數重載、屬性重載類似,這邊就不演示了,不過需要注意的是DependencyOverride是針對所註冊對象類型中所包含的對象類型重載,例如在A類中有構造函數參數是B類,同時也有個屬性依賴於B類,當使用了DependencyOverride後,這個A對象原先註冊的有關B類的依賴將全部改變
。(具體可查看示例代碼中的ResolveDependency)
三、延遲獲取對象
Unity還有個很不錯的特性就是支持延遲獲取, 其本質是通過事先建立一個委託,然後再調用這個委託,看下下面的代碼:
01
|
public
static
void
DeferringResolve()
|
03
|
var resolver = container.Resolve<Func<IClass>>();
|
08
|
container.RegisterType<IClass, MyClass>();
|
10
|
var myClass = resolver();
|
12
|
var resolver2 = container.Resolve<Func<IEnumerable<IClass>>>();
|
17
|
container.RegisterType<IClass, MyClass>(
"my"
);
|
18
|
container.RegisterType<IClass, YourClass>(
"your"
);
|
20
|
var classList = resolver2();
|
這段代碼演示了2個延遲獲取的方式,都是通過將Func<T>放入Resolve<T>中來實現的,返回的是一委託,這樣就可以在實際需要的時候再調用這個委託:
1、第一種是事先通過Resolve<Func<IClass>>(); 來定義獲取與IClass關聯的對象的委託,然後再註冊IClass與MyClass之間的關係,然後再通過resolver(); 來獲取。
2、第二種是事先通過Resolve<Func<IEnumerable<IClass>>>(); 來定義獲取一個與IClass關聯的命名實例列表的委託,然後調用相應的委託就可以一次性獲取與IClass關聯的所有命名實例。
這2種方式都很好的展示了Unity可以更加靈活的控制對象之間的註冊與對象的調用。
四、檢索容器中註冊信息
當我們在不斷使用Unity容器的過程中,我們有時候想看一下容器中到底註冊了多少對象,以及各個對象的一些信息,如:什麼對象和什麼對象關聯、具體的注
冊名稱和使用的生命週期管理器,這些信息都可以在容器的Registrations屬性中查看到,在Unity文檔中已經有個方法來查看這些信息了,代碼
如下:
01
|
public
static
void
DisplayContainerRegistrations(IUnityContainer theContainer)
|
03
|
string
regName, regType, mapTo, lifetime;
|
04
|
Console.WriteLine(
"容器中 {0} 個註冊信息:"
,
|
05
|
theContainer.Registrations.Count());
|
06
|
foreach
(ContainerRegistration item
in
theContainer.Registrations)
|
08
|
regType = item.RegisteredType.Name;
|
09
|
mapTo = item.MappedToType.Name;
|
10
|
regName = item.Name ??
"[默認]"
;
|
11
|
lifetime = item.LifetimeManagerType.Name;
|
14
|
mapTo =
" -> "
+ mapTo;
|
18
|
mapTo =
string
.Empty;
|
20
|
lifetime = lifetime.Substring(0, lifetime.Length -
"生命週期管理器"
.Length);
|
21
|
Console.WriteLine(
"+ {0}{1} '{2}' {3}"
, regType, mapTo, regName, lifetime);
|
具體的註冊代碼如下:
01
|
public
static
void
RegisterAll()
|
03
|
container.RegisterType<IClass, MyClass>(
"my"
);
|
04
|
container.RegisterType<IClass, YourClass>(
"your"
,
|
05
|
new
ExternallyControlledLifetimeManager());
|
06
|
container.RegisterType<ISubject, Subject1>(
"subject1"
);
|
07
|
container.RegisterType<ISubject, Subject2>(
"subject2"
);
|
09
|
DisplayContainerRegistrations(container);
|
效果圖如下:
可以看到,我在代碼中註冊的信息都已經很好的反應出來了。
同時如果想查看某個對象是否已經被註冊,可以通過container.IsRegistered<T>來驗證,這邊就不演示了。
以上就是本文的所有內容了,主要介紹了Unity的Register和Resolve的一些高級應用,英文好的朋友可以直接查看Unity的官方文檔。
示例代碼下載:點我下載
(注意:本文示例代碼是基於VS2010+Unity2.0,所以請使用VS2010打開,如果沒有安裝VS2010,請將相關代碼複製到相應的VS中運行既可
)
微軟企業庫5.0 學習之路系列文章索引:
第一步、基本入門
第二步、使用VS2010+Data Access模塊建立多數據庫項目
第三步、爲項目加上異常處理(採用自定義擴展方式記錄到數據庫中)
第四步、使用緩存提高網站的性能(EntLib Caching)
第五步、介紹EntLib.Validation模塊信息、驗證器的實現層級及內置的各種驗證器的使用方法——上篇
第五步、介紹EntLib.Validation模塊信息、驗證器的實現層級及內置的各種驗證器的使用方法——中篇
第五步、介紹EntLib.Validation模塊信息、驗證器的實現層級及內置的各種驗證器的使用方法——下篇
第六步、使用Validation模塊進行服務器端數據驗證
第七步、Cryptographer加密模塊簡單分析、自定義加密接口及使用—上篇
第七步、Cryptographer加密模塊簡單分析、自定義加密接口及使用—下篇
第八步、使用Configuration Setting模塊等多種方式分類管理企業庫配置信息
第九步、使用PolicyInjection模塊進行AOP—PART1——基本使用介紹
第九步、使用PolicyInjection模塊進行AOP—PART2——自定義Matching Rule
第九步、使用PolicyInjection模塊進行AOP—PART3——內置Call Handler介紹
第九步、使用PolicyInjection模塊進行AOP—PART4——建立自定義Call Handler實現用戶操作日誌記錄
第十步、使用Unity解耦你的系統—PART1——爲什麼要使用Unity?
第十步、使用Unity解耦你的系統—PART2——瞭解Unity的使用方法(1)
第十步、使用Unity解耦你的系統—PART2——瞭解Unity的使用方法(2)
第十步、使用Unity解耦你的系統—PART2——瞭解Unity的使用方法(3)
第十步、使用Unity解耦你的系統—PART3——依賴注入
第十步、使用Unity解耦你的系統—PART4——Unity&PIAB
擴展學習:
擴展學習篇、庫中的依賴關係注入(重構 Microsoft Enterprise Library)[轉]