Unity是微软Patterns & Practices团队所开发的一个轻量级的,并且可扩展的依赖注入(Dependency Injection)容器,它支持常用的三种依赖注入方式:构造器注入(Constructor Injection)、属性注入(Property Injection),以及方法调用注入(Method Call Injection).现在Unity最新的版本的1.2版,可以在微软的开源站点http://unity.codeplex.com下载最新的发布版本和文档。通过使用Unity,我们能轻松构建松耦合结构的程序,从而让整个程序框架变得清晰和易于维护。

在平常的软件编码过程中,程序的逻辑往往很复杂,尤其是大型项目的开发中,一个模块常常会去引用其他的模块,假设我们有一个监控器类,用来监控CPU的温度,当温度达到预警的范围时,监控器有一个报警的方法,方法里面通过短信提醒器,以发送短信的方式通知维护人员。于是就出现了下面这样一段最为常见的代码:

   1:  public class Monitor
   2:  {
   3:         public void Alarm()
   4:         {
   5:                 SMSNotify notify = new SMSNotify();
   6:                 notify.Send();
   7:          }
   8:  }

在Monitor类中,直接引用到了一个短信提醒器的类,这是最为不灵活和最不易于扩展的一种方式。或许我们想到了面向接口编程,利用多态的好处,可以提供灵活的不同子类的实现,增加代码扩展性等等。但是说到底,接口一定是需要实现的,也就是如下语句迟早要执行:

   1:  public void Alarm()
   2:  {
   3:         INotify notify = new SMSNotify();
   4:         notify.Send();
   5:  }

这样看来,在实现INotify这个接口的时候,仍然需要具体的类来实现,而这样的代码在程序编译的时候就已经固定下来,如果以后需要使用新的提醒器,仍旧需要修改源代码并重新编译。并且在我们的Monitor类中,明显依赖SMSNotify类,二者之间的耦合度非常紧密。因此Ioc(控制反转)模式被提出用来解决这种问题,也即把接口的具体实现延缓到运行时,接口的实现类是在运行时被装载的。这样,就算有了新的实现类,也不需要更改调用者的代码(可以在Unity中使用配置文件的方式实现)。这种Ioc模式可以被形象的比喻为:接口就像一个空壳,而在具体实现时,向这个空壳注入内容,而让它成为一个真正的实体。这种模式也被形象的称为:依赖注入。通过使用Unity,我们能构建松耦合的软件,并且对象之间相互关联的细节,我们也不必关心,可以交由依赖注入容器全权负责。

前面也提到了依赖注入常用的三种形式:构造器注入、属性注入和方法调用注入,我们可以通过例子来实现这三种形式的注入。还是以上面的场景为例:

1.Constructor Injection

IMonitor接口定义:

   1:  public interface IMonitor
   2:  {
   3:      void Alarm();
   4:  }

Monitor类:

   1:  public class Monitor : IMonitor
   2:  {
   3:      private INotify notify;
   4:  
   5:      public Monitor(INotify n)
   6:      {
   7:          notify = n;
   8:      }
   9:  
  10:      public void Alarm()
  11:      {
  12:          notify.Send();
  13:      }
  14:  }

INotify接口定义:

   1:  public interface INotify
   2:  {
   3:      void Send();
   4:  }

EmailNotify类:

   1:  public class EmailNotify : INotify
   2:  {
   3:      public void Send()
   4:      {
   5:          Console.WriteLine("Send Email Notify...");
   6:      }
   7:  }

SMSNotify类:

   1:  public class SMSNotify : INotify
   2:  {
   3:      public void Send()
   4:      {
   5:          Console.WriteLine("Send SMS Notify...");
   6:      }
   7:  }

可以看到,在Monitor类的构造函数里面,传入的参数是一个INotify接口类型,Alarm方法,调用了实现类的Send方法,但具体调用哪一个实现类的Send方法,只有在注入实体后才知道。Unity容器中,通常使用RegisterType和Resolve方法来分别注册和获取实例,并且这两个方法有很多泛型和非泛型的重载,具体的类型和参数,可以参考Unity的官方帮助文档。

现在我们向Monitor的构造函数注入实现INotify接口的实例:

   1:  static void Main(string[] args)
   2:  {
   3:      IUnityContainer container = new UnityContainer();
   4:      container.RegisterType<IMonitor, Monitor>().RegisterType<INotify, SMSNotify>();
   5:  
   6:      IMonitor monitor = container.Resolve<IMonitor>();
   7:      monitor.Alarm();
   8:  
   9:      Console.ReadLine();
  10:  }

代码中我们注入的INotify实例是SMSNotify类的实例,然后调用monitor.Alrarm(),里面会调用notify.Send().
上面是针对单个构造函数的情况,如果有多个构造函数,需要指明哪个构造函数是需要被注入的,也即需要在指定被注入的构造函数加上attribute:InjectionConstructor

   1:  public Monitor(INotify n, string name)
   2:  {
   3:      notify = n;
   4:  }
   5:  
   6:  [InjectionConstructor]
   7:  public Monitor(INotify n)
   8:  {
   9:      notify = n;
  10:  }

运行后可得到一样的结果.

2.Property Injection

通过属性注入,我们需要加上attribute: Dependency,使得Unity容器在获取类对象实例时,自动实例化该属性所依赖的对象,并注入到属性中。

修改Monitor类,实现下面的代码:

   1:  public class Monitor : IMonitor
   2:  {
   3:      [Dependency]
   4:      public INotify Notify { get; set; }
   5:  
   6:      public void Alarm()
   7:      {
   8:          Notify.Send();
   9:      }
  10:  }

再在Main函数里面,修改原有的代码,这次我们让容器注入EmailNotify实例:

   1:  container.RegisterType<INotify, EmailNotify>();

还有一个比较方便的地方,可以为Dependency特性指定名称,这样,在注入时,会将RegisterType所指定的对应名称的实体进行注入,例如:

   1:      public class Monitor : IMonitor
   2:      {
   3:          [Dependency("SMS")]
   4:          public INotify Notify { get; set; }
   5:  
   6:          public void Alarm()
   7:          {
   8:              Notify.Send();
   9:          }
  10:      }

修改Main函数,在RegisterType函数中指定注入名称:

   1:              container.RegisterType<INotify, EmailNotify>("Email");
   2:              container.RegisterType<INotify, SMSNotify>("SMS");

3.Method Call Injection

Method Call Injection注入的时机和Constructor Injection有一定的区别,构造函数注入,是在容器创建实例的时候,而方法调用注入,是在方法被调用的时候。实现方法调用注入,需要在指定注入的方法前加上attribute: InjectionMethod

修改Monitor类的代码如下:

   1:      public class Monitor : IMonitor
   2:      {
   3:          private INotify notify;
   4:  
   5:          [InjectionMethod]
   6:          public void GetNotify(INotify n)
   7:          {
   8:              notify = n;
   9:          }
  10:  
  11:          public void Alarm()
  12:          {
  13:              notify.Send();
  14:          }
  15:      }

在程序运行时,容器会自动实例化GetNotify方法所依赖的对象,并自动调用该方法,将其注入到方法中。

Main函数如下:

   1:          static void Main(string[] args)
   2:          {
   3:              IUnityContainer container = new UnityContainer();
   4:              container.RegisterType<IMonitor, Monitor>();
   5:              container.RegisterType<INotify, EmailNotify>();
   6:  
   7:              IMonitor monitor = container.Resolve<IMonitor>();
   8:              monitor.Alarm();
   9:  
  10:              Console.ReadLine();
  11:          }
摘自(http://www.lywill.com/archives/kf/2013/Microsoft-Practices-UnityRuMen/)

Microsoft.Practices.Unity入门的更多相关文章

  1. 利用Microsoft.Practices.Unity的拦截技术,实现.NET中的AOP

    1.记住这个单词的意思:Interception(拦截) 2.首先说一下原理和背景 原理:所谓的AOP就是面向切面编程,这里不多说,百度搜索. 目的:个人认为是为了解耦,部分代码跟业务代码分离,业务代 ...

  2. 第九回 Microsoft.Practices.Unity.Interception实现基于数据集的缓存(针对六,七,八讲的具体概念和配置的解说)

    返回目录 概念 Microsoft.Practices.Unity.Interception是一个拦截器,它隶属于Microsoft.Practices.Unity组成之中,主要完成AOP的功能,而实 ...

  3. Microsoft.Practices.Unity 给不同的对象注入不同的Logger

    场景:我们做项目的时候常常会引用第三方日志框架来帮助我们记录日志,日志组件的用途主要是审计.跟踪.和调试.就说我最常用的日志组件log4net吧,这个在.NET同行当中应该算是用得非常多的一个日志组件 ...

  4. Microsoft.Practices.Unity

    // // Summary: // Register a type mapping with the container. // // Parameters: // container: // Con ...

  5. VS - Microsoft.Practices.Unity

    PM>  Install-Package Unity Web.config <configSections> <section name="unity" t ...

  6. WPF Microsoft.Practices.Unity 注入大法简单示例

    最近新入职了公司,做WPF方向的项目,进来后看到这边大量运用了依赖注入来解耦,采用的是Microsoft.Practices.Unity. WPF的话,目前主要有两个技术来实现IOC,unity和ME ...

  7. 使用Microsoft.Practices.Unity 依赖注入

    Unity是微软Patterns & Practices团队所开发的一个轻量级的,并且可扩展的依赖注入(Dependency Injection)容器,它支持常用的三种依赖注入方式:构造器注入 ...

  8. 使用Microsoft.Practices.Unity 依赖注入 转载https://www.cnblogs.com/slardar1978/p/4205394.html

    Unity是微软Patterns & Practices团队所开发的一个轻量级的,并且可扩展的依赖注入(Dependency Injection)容器,它支持常用的三种依赖注入方式:构造器注入 ...

  9. 20190703_创建 unity 的配置节处理程序时出错: The type name or alias Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension

    创建 unity 的配置节处理程序时出错: The type name or alias Microsoft.Practices.Unity.InterceptionExtension.Configu ...

随机推荐

  1. C++ static

    本文主要记录的C++中static的一些内容,内容简单,仅仅作为梳理一下知识,如有错误请留言指出. static的作用 在函数体,一个被声明为static的变量,在这一函数被调用的过程里,其数值维持不 ...

  2. [Reomting Debug] 巧用VS 的remote debug 功能远程调试程序 经验分享.

    前言: 有时候我们Dev(开发人员)需要debug tester(测试人员)或者customer(客户)的环境,可tester的机器上没有Code,是不是有点着急? 而且是多版本应用且tester 发 ...

  3. Atitit blend mode COLOR_DODGE 混合模式  “颜色减淡”模式

    Atitit blend mode COLOR_DODGE 混合模式  "颜色减淡"模式 1.1. 混合模式是图像处理技术中的一个技术名词1 1.2. 目录1 1.3. 颜色减淡C ...

  4. Atitit.软件与编程语言中的锁机制原理attilax总结

    Atitit.软件与编程语言中的锁机制原理attilax总结 1. 用途 (Db,业务数据加锁,并发操作加锁.1 2. 锁得类型 排它锁 "互斥锁 共享锁 乐观锁与悲观锁1 2.1. 自旋锁 ...

  5. LigerUI Tree

    <!DOCTYPE html> <%@ page language="java" contentType="text/html; charset=utf ...

  6. Entity Framework 5中应用表值函数进行Linq查询

    Entity Framework 5引入了表值函数(Table-Valued Functions TVFs).表值函数的返回类型是一个Table类型,可用在SQL查询语句中.最简单的表值函数,读取客户 ...

  7. Ubuntu 14.04上安装caffe

    本来实在windows 10上尝试安装caffe,装了一天没装上,放弃; 改在windows上装ubuntu的双系统,装了一个下午,不小心windows的系统盘被锁死了,也不会unlock?只好含泪卸 ...

  8. codeforces——Little Pony and Expected Maximum

    /* 我们枚举每次选择最大数值的情况:m个数, 投掷n次 最大值是1: 1种 2: 2^n-1 3: 3^n-2^n ..... m: m^n-(m-1)^n 所以最后的结果=sum((k/m)^n ...

  9. Java多线程系列--“JUC集合”02之 CopyOnWriteArrayList

    概要 本章是"JUC系列"的CopyOnWriteArrayList篇.接下来,会先对CopyOnWriteArrayList进行基本介绍,然后再说明它的原理,接着通过代码去分析, ...

  10. Parallel并行化编程

    在很多场景中我们需要通过并行化的方式来提高程序运行的速度,比较典型的需求就是并行下载.前期遇到一个需求是要批量下载瓦片,每次大概下载上百万个瓦片,要想提高瓦片的下载速度,只能通过并行化的方式,下面把我 ...