Castle IOC容器内幕故事(上)

摘要:在快速入门指南篇中,我们对于Castle IOC容器的使用已经有了一个直观的认识。本文将在这基础上进一步对Castle IOC容器的结构及其注册组件的过程做一个深入的分析,让我们开始Castle IOC的内幕故事吧。

 

主要内容

1WindsorContainer分析

2MicroKernel分析

3.注册组件流程

 

一.WindsorContainer分析

WindsorContainerCastleIOC容器,也是它的一个核心,先来看一下WindsorContainerCastle中所处的位置:

1

WindsorContainer构建于MicroKernel之上,MicroKernel仅仅是提供了一个IOC的容器,非常的轻巧,它只依赖于Castle.Model一个程序集,但它的可扩展能力却很强,后面会讲到;可以这么理解,WindsorContainer为我们提供了一个Façade,它封装了MicroKernel,并且提供了一些扩展点,但它的核心仍然是Microkernel如下图所示:

2

二.MicroKernel分析

既然MicroKernelWindsorContainer的核心,那我们就来看一下MicroKernel的结构,从下面的结构图中,可以看到MicroKernel的组成主要有SubSystemComponentsFacilities几个部分,SubSystem主要用来处理一些扩展功能,如配置、类型转换等,我们也可以实现自己的SubSystemComponents称为组件,在快速入门指南中我已经提到了,这里再说一下,服务是一个个的接口,接口约定了服务,从而使随意替换服务的实现对使用接口服务的代码没有任何的影响,组件是一个可重用的程序单元,它实现了某个接口,并仅仅只实现了这一个良好的接口,也就是说,组件是实现了某个服务接口的类;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 == nullthrow new ArgumentNullException("key");

    
if (classType == nullthrow 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 == nullthrow new ArgumentNullException("key");

    
if (serviceType == nullthrow new ArgumentNullException("serviceType");

    
if (classType == nullthrow 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

最后发出ComponentRegisteredHandlerRegistered事件,完成整个组件的注册过程。

Castle IOC容器内幕故事(下)   

参考资料

Castle的官方网站http://www.castleproject.org
作者:TerryLee
出处:http://terrylee.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted @ 2006-04-18 12:24 TerryLee 阅读(9088) 评论(12)  编辑 收藏 所属分类: NHibernateCastle Project

  回复  引用  查看    
#1楼 2006-04-18 14:01 | 深渊野鱼      
冒昧问一句,这图用什么来画的?
还有,文章也不错~
  回复  引用  查看    
#2楼 [楼主]2006-04-18 14:10 | Terrylee      
@深渊野鱼
呵呵,谢谢!

图是用MS Visio画的:-)
  回复  引用  查看    
#3楼 2006-04-18 14:15 | 深渊野鱼      
~~ 最近没什么时间研究IOC.
你多研究研究,把研究成果告诉我们啊~~

哦,还有,visio的哪个模版?没找到合适的:(
  回复  引用  查看    
#4楼 [楼主]2006-04-18 14:44 | Terrylee      
@深渊野鱼
好,我研究的相关IOC的东西,都会发在我的Blog上面

我用的是Visio2003的,那个样式是设置了一个渐变效果,呵呵:-)
  回复  引用    
#5楼 2006-04-18 22:44 | 过路 [未注册用户]
很不错的文章,期待下一篇!
  回复  引用  查看    
#6楼 [楼主]2006-04-19 08:37 | Terrylee      
@过路
谢谢支持!

关于Castle IOC的文章还会继续写下去:-)
  回复  引用    
#7楼 2006-04-19 10:32 | pig [未注册用户]
无极网摘:[url]http://www.789hao.com[/url]
  回复  引用    
#8楼 2006-06-05 11:55 | xu [未注册用户]
很喜欢你的文章
  回复  引用  查看    
#9楼 [楼主]2006-06-05 12:32 | TerryLee      
@xu
谢谢:-)
  回复  引用    
#10楼 2006-08-04 17:18 | 阿潘 [未注册用户]
太感谢你了,刚看npetshop2,一头雾水,现在清晰多了
  回复  引用  查看    
#11楼 [楼主]2006-08-04 17:20 | TerryLee      
@阿潘
呵呵,太客气了:-)
  回复  引用    
#12楼 2006-09-29 17:20 | codelover [未注册用户]
.net开源框架qq群30017484,Castle ActiveRecord、Nhibernate、ibatisnet、IOC容器Spring.Net和Castle、等框架讨论学习,共同提高

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2006-04-21 11:22 编辑过


相关链接: