位置: 编程技术 - 正文

你知道Unity IoC Container是如何创建对象的吗?(你知道的,是我的兄弟 我要把天赋)

编辑:rootadmin
【狗刨学习网】

推荐整理分享你知道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 IoC Container是如何创建对象的吗?(你知道的,是我的兄弟 我要把天赋)

左图反映的就是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: public interface IBuilderContext 2: { 3: //Others... 4: bool BuildComplete { get; set; } 5: NamedTypeBuildKey BuildKey { get; set; } 6: NamedTypeBuildKey OriginalBuildKey { get; } 7: object CurrentOperation { get; set; } 8: object Existing { get; set; } 9: }

上面对IBuilderContext的定义中,简单起见,我刻意省略了一些属性。在上述的属性列表中,BuildComplete表示Build操作是否被标识为结束,如果某个BuilderStrategy已经完成了Build的操作,可以将其设置为True,这样后续的BuilderStrategy就可以根据该&#;进行相应的操作(大部分将不作进行后续的Build);BuildKey和OriginalBuildKey是一个以Type &#; Name为组合的代表当前Build操作(通过CurrentOperation表示)的键;Existing属性表示已经生成的对象,一般来讲BuilderStrategy会将自己生成的对象赋给该&#;;而Strategies则代表了整个BuilderStrategy管道。

三、创建一个最简单的BuilderStrategy

现在我们编写一个最简单不过的例子,看看UnityContainer是如何借助于BuilderStrategy管道进行对象的提供的(你可以通过这里下载源代码)。我们先来创建一个最简单不过的BuilderStrategy,我们的策略就是通过反射的方式来创建对象,为此我们将该BuilderStrategy命名为ReflectionBuilderStrategy。

1: public class ReflectionBuilderStrategy:BuilderStrategy 2: { 3: public override void PreBuildUp(IBuilderContext context) 4: { 5: if (context.BuildComplete || null != context.Existing) 6: { 7: return; 8: } 9: var value = Activator.CreateInstance(context.BuildKey.Type); : if (null != value) : { : context.Existing = value; : context.BuildComplete = true; : } : } : }

ReflectionBuilderStrategy继承自统一的基类BuilderStrategy。由于我们只需要ReflectionBuildStrategy进行对象的创建,这里我们只需要重写PreBuildUp方法。在PreBuildUp方法中,如果需要提供的对象已经存在(通过BuilderContext的Existing属性判断)或者Build操作已经完成(通过BuilderContext的BuildComplete属性判断),则直接返回。否则通过BuilderContext的BuildKey属性得到需要创建对象的类型,通过反射的机制创建该对象,将其赋给BuilderContext的Existing属性,并将BuildComplete设置成True。

现在BuilderStrategy已经创建成功,如何将它添加到UnityContainer的BuilderStrategy管道呢?一般地,我们需要为BuilderStrategy创建相应的扩展对象。为此,下面我们创建了一个继承自UnityContainerExtension的类型ReflectionContainerExtension:

1: public class ReflectionContainerExtension : UnityContainerExtension 2: { 3: protected override void Initialize() 4: { 5: this.Context.Strategies.AddNew(UnityBuildStage.PreCreation); 6: } 7: }

在ReflectionContainerExtension中,我仅仅重写了Initialize方法。在该方法中,通过Context属性得到相应UnityContainer的BuilderStrategy管道,并调用AddNew方法将我们创建的ReflectionBuilderStrategy添加进取。泛型方法AddNew接受一个UnityBuildStage类型的枚举。UnityBuildStage代表整个Build过程的某个阶段,在这里决定了添加的BuilderStrategy在管道中的位置。现在我们假设需要通过UnityContainer来创建下面一个类型为Foo的对象:

1: public class Foo 2: { 3: public Guid Id { get; private set; } 4: 5: public Foo() 6: { 7: Id = Guid.NewGuid(); 8: } 9: }

真正通过UnityContainer进行对象的提供实现在下面的代码中。由于UnityContainer在初始化的过程中会通过UnityDefaultStrategiesExtension这么一个扩展,所以我特意通过调用RemoveAllExtension将其清除。然后调用AddExtension将我们上面创建的ReflectionContainerExtension添加到UnityContainer的扩展列表中。最后3次调用UnityContainer的Resolve方法得到Foo对象,并将ID输出。

1: static void Main(string[] args) 2: { 3: IUnityContainer container = new UnityContainer(); 4: container.RemoveAllExtensions(); 5: container.AddExtension(new ReflectionContainerExtension()); 6: Console.WriteLine(container.Resolve().Id); 7: Console.WriteLine(container.Resolve().Id); 8: Console.WriteLine(container.Resolve().Id); 9: } : }

下面是输出结果:

baa0b4-cc-4d-9f8c-8ea7baf1def0cefc2-ffac--ad-fbbcdf-e-4ef9-abe0-dfd7ab四、通过自定义BuilderStrategy实现单例模式

上面的例子已经能够基本上反映出UnityContainer借助于BuilderStrategy管道的对象提供机制了。为了更加进一步的说明“管道”的存在,我们再自定义另一个简单的BuilderStrategy,实现我们熟悉的单例模式(基于UnityContainer对象来说是单例)。下面是是实现单例模式的BuilderStrategy:SingletonBuilderStrategy,和相应的Unity扩展。在SingletonBuilderStrategy中,我们通过一个静态字典用于缓存创建成功的对象,该对象在字典中的Key为创建对象的类型。被创建的对象在PostCreate方法中被缓存,在PreCreate中被返回。为了将该SingletonBuilderStrategy至于管道的前端,在添加的时候指定的UnityBuildStage为Setup。

1: public class SingletonBuilderStrategy : BuilderStrategy 2: { 3: private static IDictionary cachedObjects = new Dictionary(); 4: 5: public override void PreBuildUp(IBuilderContext context) 6: { 7: if (cachedObjects.ContainsKey(context.OriginalBuildKey.Type)) 8: { 9: context.Existing = cachedObjects[context.BuildKey.Type]; : context.BuildComplete = true; : } : } : : public override void PostBuildUp(IBuilderContext context) : { : if (cachedObjects.ContainsKey(context.OriginalBuildKey.Type) || null == context.Existing) : { : return; : } : : cachedObjects[context.OriginalBuildKey.Type] = context.Existing; : } : } : : public class SingletonContainerExtension : UnityContainerExtension : { : protected override void Initialize() : { : this.Context.Strategies.AddNew(UnityBuildStage.Setup); : } : }

现在,我们将基于SingletonBuilderStrategy的扩展添加到之前的程序中。再次运行我们的程序,你会发现输出的ID都是一样的,由此可见三次创建的对象均是同一个。

1: class Program 2: { 3: static void Main(string[] args) 4: { 5: IUnityContainer container = new UnityContainer(); 6: container.RemoveAllExtensions(); 7: container.AddExtension(new ReflectionContainerExtension()); 8: container.AddExtension(new SingletonContainerExtension()); 9: Console.WriteLine(container.Resolve().Id); : Console.WriteLine(container.Resolve().Id); : Console.WriteLine(container.Resolve().Id); : } : }

输出结果:

e-e7-f7-ad-de-e7-f7-ad-de-e7-f7-ad-d

总结:虽然Unity具体的实现机制相对复杂,但是其本质就是本文所介绍的基于BuilderStrategy&#;BuilderContext的Pipeline&#;Context的机制。当你在研究Unity的具体实现原理的时候,抓住这个原则会让你不至于迷失方向。

声明:此篇文档时来自于【狗刨学习网】社区,是网友自行发布的Unity3D学习文章,如果有什么内容侵犯了你的相关权益,请与官方沟通,我们会即时处理。更多精彩内容:www.gopedu.com

unity之台湾游戏教父王俊博:做永远的抬轿人 狗刨学习网报道王俊博,台湾智冠集团董事长,年创立智冠科技有限公司,驰骋游戏行业余年,被称为台湾游戏界教父和老顽童。然而,亲手创立

unity游戏之年度最佳游戏奖项名单公布 狗刨学习网报道/羊年新年之际,狗刨学习网首先向多年来支持狗刨学习网的游戏业同行拜年了!祝大家羊年阖家欢乐、万事如意、三阳开泰、恭喜发财

土豪手游:[糖果传奇]累计收入破亿元 【狗刨学习网专稿,转载请注明出处】狗刨学习网报道/在King前几天刚刚发布的财报当中,该公司并没有具体透露《糖果传奇》的太多细节数据,不过,

标签: 你知道的,是我的兄弟 我要把天赋

本文链接地址:https://www.jiuchutong.com/biancheng/380232.html 转载请保留说明!

上一篇:全面理解 Unity UI 系统(全面理解和准确把握新时代党的建设总要求心得体会)

下一篇:unity之台湾游戏教父王俊博:做永远的抬轿人(台湾 游戏论坛)

  • 所得税费用科目属于什么科目
  • 税率中的速算扣除数是什么
  • 行政事业单位决算编制流程图
  • 将自产产品用于在建工程要交增值税
  • 去年滞纳金没入营业外今天怎么账务处理
  • 个人独资企业可以转让股权吗
  • 年初未分配利润和年末未分配利润的关系
  • 应付职工薪酬工资贷方有余额要怎么调整
  • 收到保险公司开票怎么做账
  • 提供教育服务免征增值税文件
  • 收取不合规发票怎么处理
  • 先开了发票给客户,不付款怎么办
  • 开票方没缴税咋办
  • 广告费收入是不是非税收入
  • 其他应交款入哪个科目
  • 神州优车开具的客运服务费入什么科目?
  • 营改增租金收入税率
  • 给员工发中秋福利
  • 企业购买房产可以抵扣增值税吗
  • 公司购买商业险多少钱
  • 低值易耗品一次性摊销体现重要性
  • 开具房屋租赁发票税率
  • 会计学堂值得购买吗
  • 单位给员工发工资要交税吗
  • 居间合同怎么签才算有效
  • 汇总纳税企业的分公司如何享受税收优惠政策
  • 公司工会发给职工的福利
  • 一般纳税人增值税及附加税费申报表怎么填
  • 冲暂估怎么做分录
  • 快启动u盘怎么打开
  • 税控设备抵减增值税会计处理
  • 结转已销产品实收成本
  • 【深度学习】目标检测的性能评价指标,mAP_0.5,mAP_0.5,0.95,0.05
  • 【机器学习】KNN算法及K值的选取
  • ctf web2
  • ps打不出字怎么回事
  • 去哪儿网发票能不能不开旅游
  • 查询公司对公账户
  • 上个月的票这个月作废后报增值税需不需要交费?
  • 微众银行的企业贷款好批吗
  • 13%和17%税率
  • 增值税和个人所得税怎么算
  • 现金流量表格式有几种
  • 收到销项负数发票怎么做分录
  • 电信线路租用费用
  • 成本增加比例怎么算的
  • 固定资产清理账户借方的核算内容包括
  • 工业企业应通过其他应付款科目核算的有
  • 原始凭证的主要内容包括
  • 会计审核外来凭证怎么做
  • win8.1关机没反应
  • Linux Kernel 4.2下载 更新内容一览
  • 微型创新是什么
  • 官方发布预防新冠戴口罩指引
  • 电脑更新windows11后开机一黑屏
  • windows软件类型最新版本
  • win8.1系统更新后启动不了
  • xp系统设置壁纸
  • MSAPI.DAT,WINDNSAPI.DAT是什么文件
  • win10系统命令大全
  • macbookair怎么验证
  • win8的计算器在哪里
  • windows10已激活
  • win7系统浏览器不见了
  • linux创建目录函数
  • js的forin
  • jquery 插件写法
  • 复制到文件夹怎么弄
  • 行为怪异的人有问题吗
  • jquery给复选框赋值
  • android 设置背景
  • javascriptj
  • 福建省电子税务局官网登录入口
  • 农机行业的市场前景
  • 电信业务发票
  • 企业税收筹划中的涉税风险及其防范
  • 新加坡税务局电邮
  • 丰田2.0和2.5混动发动机
  • 个人转让住宅需要缴纳什么税
  • 双流税务总局电话
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设