三、IResolver<TService>和SingleServiceResolver<TService>:IResolver<TService>、MultiServiceResolver<TService>:IResolver<IEnumerable<TService>>
IResolver<TService>介面只有一個TService型的Current唯讀屬性,返回相應類型的一個對象。這是一個有Lazy意味的輕量介面。
一個簡單的IResolver<TService>介面的實作類別中,Current可以返回Activator.CreateInstance建立的執行個體——在面向介面編程方面講,完全是有意義的。
SingleServiceResolver類是IResolver<TService>的實現,它用於擷取單個對象,其實現原理是:在構造對象時,方法內部或作為參數指定一種預設的對象建立(擷取)"方式"——方式1,作為參數傳入另一種建立(擷取)"方式"——方式2和當
當兩種建立(擷取)對象都不成功的情況下(兩種方式都成功,則會拋出異常)提供一個預設對象。
具體來說,在它公用的構造方法中,指定的方式1為DependencyResolver.Current(IDependencyResolver)。
當調用SingleServiceResolver類的Current屬性時,首先判斷如果方式1不為null,則通過DependencyResolver.Current.GetService(typeof(TService))擷取一個TService對象,如果建立(擷取)成功,則嘗試方式2建立(擷取),如果也成功則拋出異常。
傳回值的時候,先判方式1如果為null,則擷取方式2的執行結果,如果結果不為null,則返回該結果,否則返回預設對象。
在它的internal構造方法中,還允許傳入預設建立(擷取)方式以賦給方式1。在兩個構造方法中還允許傳入一個字串標明是哪個方法在建立SingleServiceResolver對象(或者說Current返回的對象)。在有異常發生時,可以將該字串傳入異常對象。
MultiServiceResolver類也是IResolver<TService>的實現,它用於擷取一個集合對象,其實現原理是:在構造對象時,方法內部或作為參數指定一種預設的對象建立(擷取)"方式"——方式1,作為參數傳入另一種建立(擷取)"方式"——方式2。
返回兩種方式建立(擷取)的集合的合集。
具體來說,在它公用的構造方法中,指定的方式1為DependencyResolver.Current(IDependencyResolver)。
當調用MultiServiceResolver類的Current屬性時,首先判斷如果方式1不為null,則通過DependencyResolver.Current.GetServices(typeof(TService))擷取一個IEnumerable<TService>對象,該集合對象可以沒有元素但不能為null,
然後將方式2建立的集合與方式1建立(擷取)的集合合并返回。
四、ControllerBuilder
我們知道在MVC2中,Controller通過ControllerFactory建立,而ControllerFactory通過ControllerBuilder的單例ControllerBuilder.Current的GetControllerFactory()方法擷取。類的預設構造方法中會初始化一個DefaultControllerFactory對象,並通過SetControllerFactory方法將其封裝成一個Func<IControllerFactory>執行個體,並賦值給_factoryThunk私人委託,當調用GetControllerFactory方法時,返回的是該委託的執行結果。
在MVC3中,ControllerBuilder類的構造方法和GetControllerFactory方法的實現又有所不同。
ControllerBuilder有一個IResolver<IControllerFactory>型的私人變數_serviceResolver。從上面的分析我們知道,IResolver<IControllerFactory>有唯一的唯讀屬性T Current,調用_serviceResolver.Current將返回一個IControllerFactory對象。
預設構造不再直接建立DefaultControllerFactory對象,只是簡單的調用新增的接受一個IResolver<IControllerFactory>介面參數的構造方法。該方法目前是internal的。
internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver) {
_serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>(
() => _factoryThunk(),
new DefaultControllerFactory { ControllerBuilder = this },
"ControllerBuilder.GetControllerFactory"
);
}
在有參構造方法內部,如果傳入的參數serviceResolver為null則建立一個實現了IResolver<IControllerFactory>介面的SingleServiceResolver<TService>類的對象賦給私人變數_serviceResolver。ControllerBuilder.Current是一個通過預設建構函式建立的對象,用到了單例模式。所以這裡serviceResolver參數是為null的。
深入SingleServiceResolver類內部我們知道,它首先會嘗試從DependencyResolver.Current.GetService(typeof(IControllerFactory))擷取IControllerFactory對象,在預設情況會調用Activator.CreateInstance(typeof(IControllerFactory)),當然會是null。所以最終會建立DefaultControllerFactory作為我們的預設ControllerFactory。
假設定義了一個UnityControllerFactory:IControllerFactory。
首先,我們可以像MVC2中那樣使用SetControllerFactory設定IControllerFactory
假設我們又實現了一個UnityDependencyResolver:IDenpendencyResovler,並將其設定為當前的IDenpendencyResovler。
在UnityContainer中將UnityControllerFactory映射到IControllerFactory介面,同樣可以達到設定ControllerFactory的目的。
另外,GetControllerFactory方法返回的不再是像MVC2中的_factoryThunk的執行結果,而是_serviceResolver的Current屬性。