Microsoft.Practices.Unity入门
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入门的更多相关文章
- 利用Microsoft.Practices.Unity的拦截技术,实现.NET中的AOP
1.记住这个单词的意思:Interception(拦截) 2.首先说一下原理和背景 原理:所谓的AOP就是面向切面编程,这里不多说,百度搜索. 目的:个人认为是为了解耦,部分代码跟业务代码分离,业务代 ...
- 第九回 Microsoft.Practices.Unity.Interception实现基于数据集的缓存(针对六,七,八讲的具体概念和配置的解说)
返回目录 概念 Microsoft.Practices.Unity.Interception是一个拦截器,它隶属于Microsoft.Practices.Unity组成之中,主要完成AOP的功能,而实 ...
- Microsoft.Practices.Unity 给不同的对象注入不同的Logger
场景:我们做项目的时候常常会引用第三方日志框架来帮助我们记录日志,日志组件的用途主要是审计.跟踪.和调试.就说我最常用的日志组件log4net吧,这个在.NET同行当中应该算是用得非常多的一个日志组件 ...
- Microsoft.Practices.Unity
// // Summary: // Register a type mapping with the container. // // Parameters: // container: // Con ...
- VS - Microsoft.Practices.Unity
PM> Install-Package Unity Web.config <configSections> <section name="unity" t ...
- WPF Microsoft.Practices.Unity 注入大法简单示例
最近新入职了公司,做WPF方向的项目,进来后看到这边大量运用了依赖注入来解耦,采用的是Microsoft.Practices.Unity. WPF的话,目前主要有两个技术来实现IOC,unity和ME ...
- 使用Microsoft.Practices.Unity 依赖注入
Unity是微软Patterns & Practices团队所开发的一个轻量级的,并且可扩展的依赖注入(Dependency Injection)容器,它支持常用的三种依赖注入方式:构造器注入 ...
- 使用Microsoft.Practices.Unity 依赖注入 转载https://www.cnblogs.com/slardar1978/p/4205394.html
Unity是微软Patterns & Practices团队所开发的一个轻量级的,并且可扩展的依赖注入(Dependency Injection)容器,它支持常用的三种依赖注入方式:构造器注入 ...
- 20190703_创建 unity 的配置节处理程序时出错: The type name or alias Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension
创建 unity 的配置节处理程序时出错: The type name or alias Microsoft.Practices.Unity.InterceptionExtension.Configu ...
随机推荐
- IOS Animation-CABasicAnimation、CAKeyframeAnimation详解&区别&联系
1.先看看网上流传的他们的继承图: 从上面可以看出CABasicAnimation与CAKeyframeAnimation都继承于CAPropertyAnimation.而CAPropertyAnim ...
- Android开发学习之路-下拉刷新以及GridView的使用
GridView是类似于ListView的控件,只是GridView可以使用多个列来呈现内容,而ListView是以行为单位,所以用法上是差不多的. 主布局文件,因为要做下拉刷新,所以加了一个Prog ...
- Markdown快速入门
现在博文写作次数渐渐变多,经常看到很多园友的博文样式都非常的美观,个人虽然是个土鳖,但对美也是有很强需求的,同时由于最近将要上线一个博客项目,因此也很关心如何可以更高效的编辑和发布博文.之前一直使用w ...
- Java并发包中Semaphore的工作原理、源码分析及使用示例
1. 信号量Semaphore的介绍 我们以一个停车场运作为例来说明信号量的作用.假设停车场只有三个车位,一开始三个车位都是空的.这时如果同时来了三辆车,看门人允许其中它们进入进入,然后放下车拦.以后 ...
- TSql 分层和递归查询
1,需求分析 在TSql中实现层次结构,例如有这样一种数据结构,省,市,县,乡,村,如何使用一张表表示这种数据结构,并且允许是不对称的,例如,上海市是个直辖市,没有省份. create table d ...
- 【资源】C++学习资料 - 逆天整理 - 精华无密版【最新】
再失效就太无语了,链接都是多份的~~—————————————————基础——————————————C++环境搭建(全套)http://pan.baidu.com/s/1o6y0smY链接:http ...
- 【WP 8.1开发】同时更新多种磁贴
一般应用程序都会包含多个尺寸的磁贴,如小磁贴(71×71).中磁贴(150×150)和宽磁贴(310×150).常规的磁贴更新做法是用XML文档来定义更新内容,然后再提交更新.如: <tile& ...
- 利用libpcap打印ip包
#include <stdio.h> #include <pcap.h> #include <time.h> #include <netinet/in.h&g ...
- MySQL PXC 高可用集群搭建
一些名词介绍: WS:write set 写数据集 IST: Incremental State Transfer 增量同步 SST:State Snapshot Transfer 全量同 ...
- Java多线程系列--“基础篇”04之 synchronized关键字
概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ...