主要內容
1.WindsorContainer分析
2.MicroKernel分析
3.注冊組件流程
一.WindsorContainer分析
WindsorContainer是Castle的IOC容器,也是它的一個核心,先來看一下WindsorContainer在Castle中所處的位置:
圖1
WindsorContainer構建於MicroKernel之上,MicroKernel僅僅是提供了一個IOC的容器,非常的輕巧,它只依賴於Castle.Model一個程序集,但它的可擴展能力卻很強,後面會講到;可以這麼理解,WindsorContainer為我們提供了一個Façade,它封裝了MicroKernel,並且提供了一些擴展點,但它的核心仍然是Microkernel。如下圖所示:
圖2
二.MicroKernel分析
既然MicroKernel是WindsorContainer的核心,那我們就來看一下MicroKernel的結構,從下面的結構圖中,可以看到MicroKernel的組成主要有SubSystem,Components,Facilities幾個部分,SubSystem主要用來處理一些擴展功能,如配置、類型轉換等,我們也可以實現自己的SubSystem;Components稱為組件,在快速入門指南中我已經提到了,這裡再說一下,服務是一個個的接口,接口約定了服務,從而使隨意替換服務的實現對使用接口服務的代碼沒有任何的影響,組件是一個可重用的程序單元,它實現了某個接口,並僅僅只實現了這一個良好的接口,也就是說,組件是實現了某個服務接口的類;Facilities我們稱之為擴張單元,如果我們想擴張容器的功能,可以通過創建擴張單元來實現,我們可以在擴張單元裡面訂閱容器事件,給組件附加屬性,建立攔截器,控制組件生命周期等,擴張單元是以一種插件的形式存在的,所以非常便於擴展,可以編寫自己的擴張單元,後面我會寫Castle自帶的一些擴張單元的使用。MicroKernel的結構如下圖:
圖3
三.注冊組件流程
現在我們來看一下當注冊一個組件時,容器做了什麼?
public virtual void AddComponent(String key, Type classType)
{
_kernel.AddComponent(key, classType);
}
public virtual void AddComponent(String key, Type serviceType, Type classType)
{
_kernel.AddComponent(key, serviceType, classType);
}
// http://terrylee.cnblogs.com
可以看到,WindsorContainer僅僅是調用了MicroKernel的方法來完成組件的注冊,它只是對MicroKernel做了一次封裝,核心的功能都由MicroKernel來完成,看一下MicroKernel中的AddComponent()方法的實現
public virtual void AddComponent(String key, Type classType)
{
if (key == null) throw new ArgumentNullException("key");
if (classType == null) throw new ArgumentNullException("classType");
ComponentModel model = ComponentModelBuilder.BuildModel(key, classType, classType, null);
RaiseComponentModelCreated(model);
IHandler handler = HandlerFactory.Create(model);
RegisterHandler(key, handler);
}
public virtual void AddComponent(String key, Type serviceType, Type classType)
{
if (key == null) throw new ArgumentNullException("key");
if (serviceType == null) throw new ArgumentNullException("serviceType");
if (classType == null) throw new ArgumentNullException("classType");
ComponentModel model = ComponentModelBuilder.BuildModel(key, serviceType, classType, null);
RaiseComponentModelCreated(model);
IHandler handler = HandlerFactory.Create(model);
RegisterHandler(key, handler);
}
// http://terrylee.cnblogs.com
先做一些必要的異常處理,然後為當前組件創建ComponentModel實例,ComponentModel獲取當前組件的詳細元信息,而且這個信息在容器中的任何地方都可以使用,所以ComponentModel其實就是組件的一個“元信息庫”。創建ComponentModel的過程如下:
public ComponentModel BuildModel(String key, Type service,
Type classType, IDictionary extendedProperties)
{
ComponentModel model = new ComponentModel(key, service, classType);
if (extendedProperties != null)
{
model.ExtendedProperties = extendedProperties;
}
foreach(IContributeComponentModelConstruction contributor in contributors)
{
contributor.ProcessModel( kernel, model );
}
return model;
}
// http://terrylee.cnblogs.com
創建ComponentModel的過程其實就是調用contributor來對組件進行處理,它會按照順序對添加進來的contributor依次調用,在DefaultComponentModelBuilder一共注冊了八個Contributor,分別為:
protected virtual void InitializeContributors()
{
AddContributor( new ConfigurationModelInspector() );
AddContributor( new LifestyleModelInspector() );
AddContributor( new ConstructorDependenciesModelInspector() );
AddContributor( new PropertiesDependenciesModelInspector() );
AddContributor( new MethodMetaInspector() );
AddContributor( new LifecycleModelInspector() );
AddContributor( new ConfigurationParametersInspector() );
AddContributor( new InterceptorInspector() );
}
// http://terrylee.cnblogs.com
這八個Contributor形成了一個處理組件的流程,它們涵蓋了組件處理流程中的配置,生命周期,構造函數依賴,屬性依賴等方面,每一個Contributor只負責某一方面的事情。再下來一步就是發出ComponentModelCreated事件了,這步的操作很簡單
protected virtual void RaiseComponentModelCreated(ComponentModel model)
{
ComponentModelDelegate eventDelegate = (ComponentModelDelegate) events[ComponentModelCreatedEvent];
if (eventDelegate != null) eventDelegate(model);
}
// http://terrylee.cnblogs.com
現在ComponentModel創建完成,該是創建IHandler了,IHandler並不做創建組件的工作,它主要的功能是創建ComponentActivator,而ComponentActivator則是完成容器的組件創建工作,它首先會根據ComponentModel“信息庫”檢查相關的依賴,檢查通過後根據生命周期管理來創建不同類型的組件,創建DefaultHandler的代碼如下:
public virtual IHandler Create(ComponentModel model)
{
IHandler handler = new DefaultHandler(model);
handler.Init(kernel);
return handler;
}
//http://terrylee.cnblogs.com
ComponentRegistered、HandlerRegistered事件,完成整個組件的注冊過程。