你知道Unity IoC Container是如何创建对象的吗?

【狗刨学习网】

Unity是微软P&P推出的一个开源的IoC框架,最新的官方版本是2.0。Unity之前的版本建立在一个称为ObjectBuild的组件上,熟悉EnterLib的读者,相信对ObjectBuild不会感到陌生。对于EnterLib 5.0之前的版本,ObjectBuild可以说是所有Application Block的基石。ObjectBuild提供一种扩展、可定制的对象创建方式,虽然微软官方没有将ObjectBuild和IoC联系在一起,其本质可以看成是一个IoC框架。在Unity 2.0中,微软直接将ObjectBuild(实际上是ObjectBuild的第二个版本ObjectBuild2)的绝大部分功能实现在了Unity中,而EnterLib则直接建立在Unity之上。由此可见Unity在EnterLib以及微软其他一些开源框架(比如Software Factory)中的重要地位。

之前园子里也有一些介绍EnterLib的文章,其中也不乏对Unity/ObjectBuild的介绍。虽然微软官方声称Unity是一个轻量级的IoC框架,但是并不意味着Unity会很简单。也正是因为Unity/ObjectBuild的复杂性,很多人撰文介绍Unity/ObjectBuild的时候,往往为了面面俱到,导致很多读者不知所云。最终的结果是,了解Unity/ObjectBuild的读者能够看懂,不懂的人读了还是不懂。在本篇文章中,我试着换一种介绍方式:抓住Unity/ObjectBuild最本质的东西,剔除一些细枝末节,希望以一种全新的视角让读者了解Unity的本质。

一、从管道+上下文(Pipeline+Context)模式说起

如果要说Unity Container采用的怎样的设计/架构模式的话,我的回答是“管道+上下文(Pipeline + Context)模式”(我不知道是否真的具有这样一种叫法)。在《WCF技术剖析(卷1)》中介绍Binding一章中,我曾经对该模式作了一个类比:“比如有一个为居民提供饮用水的自来水厂,它的任务就是抽取自然水源,进行必要的净化处理,最终输送到居民区。净化处理的流程可能是这样的:天然水源被汲取到一个蓄水池中先进行杂质的过滤(我们称这个池为过滤池);被过滤后的水流到第二个池子中进行消毒处理(我们称这个池为消毒池);被消毒处理的水流到第三个池子中进行水质软化处理(我们称这个池为软化池);最终水通过自来水管道流到居民的家中。”

当我们需要创建一个基础架构对某种元素(例子中需要进行处理的水)进行一系列处理的时候,我们就可以将相应的处理逻辑(例子中的过滤、消毒和软化)实现在相应“节点”(例子中的过滤池、消毒池和软化池 )中。根据需要(比如水质情况)对相应的节点进行有序组合(水质的不同决定了处理工序的差异)从而构成一个管道(自来水厂整个水处理管道)。由于每一个节点具有标准的接口,我们可以对组成管道的各个节点具有任意重组,也可以为某种需要自定义节点,从而使我们的“管道”变得能够适应所有的处理需要。

对于这样的设计,其实我们并不陌生。比如ASP.NET的运行时就可以看成是一个由若干HttpModule组成的处理HTTP请求的管道,WCF中Binding就是一个由若干信道(Channel)组成的处理Message的管道。相同的设计还体现在.NET Remoting, BizTalk等相关框架和产品的设计上。

基于相应标准的“节点”进行有序组合构成管道,但是各个相对独立的节点如何进行相应的协作呢?这就需要在整个管道范围内共享一些上下文(Context),上下文是对管道处理对象和处理环境的封装。ASP.NET运行时管道的上下文对象是HttpContext,而Binding管道的上下文是BindingContext。

二、UnityContainer是BuildStrategy的管道

作为一个IoC框架,Unity Container的最终目的动态地解析和注入依赖,最终提供(创建新对象或者提供现有对象)一个符合你要求的对象。为了让整个对象提供处理流程变得可扩展和可订制,整个处理过程被设计成一个管道。管道的每一个节点被称为BuilderStrategy,它们按照各自的策略参与到整个对象提供处理流程之中。

除了对象的提供功能之外,Unity Container还提供另一个相反的功能:对象的回收。我们暂且将两者称之为Build-Up和Tear-Down。Build-Up和Tear-Down采用相同的处理机制。

左图反映的就是Unity Container由若干BuilderStrategy组成的一个用于进行对象的Build-Up和Tear-Down的管道。每一个BuildStrategy具有相同的接口(这个接口是IBuilderStrategy),它们具有四个标准的方法:PreBuildUp、PostBuildUp、PreTearDown和PostTearDown。从名称我们不难看出,四个方法分别用于完成对象创建前/后和对象回收前后相应的操作。具体来说,当需要利用该管道创建某个对象的时候,先按照BuilderStrategy在管道中的顺序调用PreBuildUp方法,到管道底端后,按照相反的顺序调用PostBuildUp方法。

对于组成Unity Container管道的各个BuilderStrategy来说,它们彼此是相互独立的,一个BuilderStrategy只需要完成基于自身策略相应的操作,不需要知道其他BuilderStrategy的存在。只有这样才能实现对管道的灵活定制,真正实现可扩展。但是在真正工作的时候,彼此之间需要共享一些上下文以促进相互协作。在这里,BuilderContext起到了这样的作用。在Unity中,BuilderContext实现了IBuilderContext,我们不妨来看看IBuilderContext定义了些什么:

1:publicinterfaceIBuilderContext 2:{ 3: //Others… 4: boolBuildComplete { get; set; } 5: NamedTypeBuildKey BuildKey { get; set; } 6: NamedTypeBuildKey OriginalBuildKey { get; } 7: objectCurrentOperation { get; set; } 8: objectExisting { get; set; } 9:}那段雨骤风狂。人生之旅本就是风雨兼程,是要说曾经拥有,

你知道Unity IoC Container是如何创建对象的吗?

相关文章:

你感兴趣的文章:

标签云: