专栏首页大内老A一个简单的小程序演示Unity的三种依赖注入方式

一个简单的小程序演示Unity的三种依赖注入方式

今天写《WCF技术剖析(卷2)》关于《WCF扩展》一章,举了“如何通过WCF扩展实现与IoC框架(以Unity为例)集成”(《通过自定义ServiceHost实现对WCF的扩展[实例篇]》)的例子。为了展示Unity如何实现几种典型的注入方式(构造器注入、属性注入和方法注入),我写了一个简单的小程序。如果读者对Unity或者IoC没有太多概念,我觉得这个小程序对于你初步地认识它们具有一定的帮助意义。如果你对Unity或者IoC有深入的认识,请忽略本文。[源代码从这里下载]

首先创建一个控制台程序,并添加如下两个基于Unity的程序集被引用:Microsoft.Practices.Unity.dll和Microsoft.Practices.Unity.Configuration.dll。然后定义如下几个接口(IA、IB、IC和ID)和它们各自的实现类(A、B、C、D)。在类型A中定义了3个属性B、C和D,其类型分别为接口IB、IC和ID。其中属性B在构在函数中被初始化;属性C上应用了Microsoft.Practices.Unity.DependencyAttribute特性,意味着这是一个需要以属性注入方式被初始化的依赖属性;属性D则通过方法Initialize初始化,该方法上应用了Microsoft.Practices.Unity.InjectionMethodAttribute,意味着这是一个注入方法会被自动调用。

   1: namespace UnityDemo
   2: {
   3:     public interface IA { }
   4:     public interface IB { }
   5:     public interface IC { }
   6:     public interface ID {}
   7:  
   8:     public class A : IA
   9:     {
  10:         public IB B { get; set; }
  11:         [Dependency]
  12:         public IC C { get; set; }
  13:         public ID D { get; set; }
  14:  
  15:         public A(IB b)
  16:         {
  17:             this.B = b;
  18:         }
  19:         [InjectionMethod]
  20:         public void Initialize(ID d)
  21:         {
  22:             this.D = d;
  23:         }
  24:     }
  25:     public class B: IB{}
  26:     public class C: IC{}
  27:     public class D: ID{}
  28: }

然后我们为该应用添加一个配置文件,并定义如下一段关于Unity的配置。在这段配置中,定义了一个名称为defaultContainer的Unity容器,并在其中完成了上面定义的接口和对应实现类之间映射的类型匹配。

   1: <?xml version="1.0"?>
   2: <configuration>
   3:   <configSections>
   4:     <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
   5:   </configSections>
   6:   <unity>
   7:     <containers>
   8:       <container name="defaultContainer">
   9:         <register type="UnityDemo.IA, UnityDemo" mapTo="UnityDemo.A, UnityDemo"/>
  10:         <register type="UnityDemo.IB, UnityDemo" mapTo="UnityDemo.B, UnityDemo"/>
  11:         <register type="UnityDemo.IC, UnityDemo" mapTo="UnityDemo.C, UnityDemo"/>
  12:         <register type="UnityDemo.ID, UnityDemo" mapTo="UnityDemo.D, UnityDemo"/>
  13:       </container>
  14:     </containers>
  15:   </unity> 
  16: </configuration>

最后在Main方法中编写如下的程序:创建一个代表IoC容器的UnityContainer对象,并加载配置信息对其进行初始化。然后调用它的泛型的Resolve方法创建一个实现了泛型接口IA的对象。最后将返回对象转变成类型A,并检验其B、C和D属性是否是空。

   1: static void Main(string[] args)
   2: {
   3:     IUnityContainer container = new UnityContainer();
   4:     UnityConfigurationSection configuration = (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName);
   5:     configuration.Configure(container, "defaultContainer");
   6:     A a = container.Resolve<IA>() as A;
   7:     if (null != a)
   8:     {
   9:         Console.WriteLine("a.B == null ? {0}", a.B == null ? "Yes" : "No");
  10:         Console.WriteLine("a.C == null ? {0}", a.C == null ? "Yes" : "No");
  11:         Console.WriteLine("a.D == null ? {0}", a.D == null ? "Yes" : "No");
  12:     }
  13: }

从如下给出的执行结果我们可以得到这样的结论:通过Resolve<IA>方法返回的是一个类型为A的对象;该对象的三个属性被进行了有效的初始化。这个简单的程序分别体现了接口注入(通过相应的接口根据配置解析出相应的实现类型)、构造器注入(属性B)、属性注入(属性C)和方法注入(属性D)。

   1: a.B == null ? No
   2: a.C == null ? No
   3: a.D == null ? No

关于IoC/DI

所谓控制反转(IoC: Inversion Of Control)就是应用本身不负责依赖对象的创建和维护,而交给一个外部容器来负责。这样控制权就由应用转移到了外部IoC容器,控制权就实现了所谓的反转。比如,在类型A中需要使用类型B的实例,而B实例的创建并不由A来负责,而是通过外部容器来创建。

有时我们又将IoC成为依赖注入(DI: Dependency Injection)。所谓依赖注入,就是由外部容器在运行时动态地将依赖的对象注入到组件之中。具体的依赖注入方式又包括如下三种典型的形式。

  • 构造器注入(Constructor Injection):IoC容器会智能地选择选择和调用适合的构造函数以创建依赖的对象。如果被选择的构造函数具有相应的参数,IoC容器在调用构造函数之前会自定义创建相应参数对象;
  • 属性注入(Property Injection):如果需要使用到被依赖对象的某个属性,在被依赖对象被创建之后,IoC容器会自动初始化该属性;
  • 方法注入(Method Injection):如果被依赖对象需要调用某个方法进行相应的初始化,在该对象创建之后,IoC容器会自动调用该方法。

在开源社区,具有很有流行的IoC框架,比如Castle Windsor、Unity、Spring.NET、StructureMap、Ninject等。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • WCF服务端运行时架构体系详解[下篇]

    作为WCF中一个核心概念,终结点在不同的语境中实际上指代不同的对象。站在服务描述的角度,我们所说的终结点实际上是指ServiceEndpoint对象。如果站在W...

    蒋金楠
  • ASP.NET Core中的依赖注入(1):控制反转(IoC)

    ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的...

    蒋金楠
  • ASP.NET Core真实管道详解[1]:中间件是个什么东西?

    ASP.NET Core管道虽然在结构组成上显得非常简单,但是在具体实现上却涉及到太多的对象,所以我们在 《ASP.NET Core管道深度剖析[共4篇]》 中...

    蒋金楠
  • SAS EG-切换local SAS

    小编最近遇到了个问题,SAS9.3马上要到期了,想把SAS EG的底层SAS切换为9.4。

    崔洞洞
  • 漏洞追踪:最新IE UXSS漏洞技术分析

    最近David Leo在Full Disclosure上爆出了一个ie的 uxss 漏洞,可以绕过ie的同源策略。FreeBuf也有相关的报道(点我查看)。本文...

    FB客服
  • Macheine Learning Yearning学习笔记(九)

    假设要构建一个系统来检查在线评论,识别正面和负面观点的问题被称为“情感分类”。为了构建该系统,可以构建两个组件的“流水线”:

    yuquanle
  • 一条SQL语句的执行计划变化探究(r10笔记第9天)

    继续上次分析的一个问题,一个简单的SQL语句执行计划有些奇怪,明明可以走唯一性索引但是却走了另外一个索引。 当然了,最后逐步定位,发现是在直方图...

    jeanron100
  • EasyNVR H5无插件直播方案前端构建之:播放界面添加实时云台控制界面

    对于实时直播的视频播放, 由于播放页面客观样式要求(一个播放器占据了整个页面),因此很难找出很合理的空间来放置其他功能按钮的位置(比如配合实时的云平台控制界...

    EasyNVR
  • EntityFramework 元数据 设计分析

        由于之前已经尝试使用过 EF CodeFirst CTP4,所以这次在EF4.1发布的第三天,在 OEA 框架中已经支持使用它来实现数据访问层。而且,我...

    用户1172223
  • 孟山都借助人工智能帮助作物抗击病害

    据外媒报道,孟山都公司(美国著名农业生化公司)因其对农业采取的技术驱动型方法而招致了很多批评,但它的最新成果可能刚好暗示了农业的未来。孟山都公司正与Atomwi...

    人工智能快报

扫码关注云+社区

领取腾讯云代金券