(转)[EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART3——依赖注入
2010-11-29 17:50
936 查看
原文地址:/article/4792194.html
继续学习Unity,在前几篇中已经将Unity的使用方法做了一个还算详细的介绍了,主要是如何通过代码及配置文件来注册对象之间的关系、Unity内置所有的生命周期管理使用介绍,及Unity的Register和Resolve的一些高级应用。通过在PART1——为什么要使用Unity?的学习我们知道Unity可以帮我们简化并管理对象之间的关系(也就是前几篇所介绍的),而今天则要介绍Unity的另外一个重要功能——DI(依赖注入)。
本篇文章将主要介绍:
1、构造函数注入。
2、属性注入。
3、方法注入。
4、使用配置完成各种注入。
5、对已经创建对象进行注入。
继续学习Unity,在前几篇中已经将Unity的使用方法做了一个还算详细的介绍了,主要是如何通过代码及配置文件来注册对象之间的关系、Unity内置所有的生命周期管理使用介绍,及Unity的Register和Resolve的一些高级应用。通过在
本篇文章将主要介绍:
2、属性注入。
3、方法注入。
4、使用配置完成各种注入。
5、对已经创建对象进行注入。
[b]一、构造函数注入[/b]
在有些时候,我们所编写的类中的构造函数都会包含对其他对象的引用,如下代码:
1 | public Subject2(MyClassmyClass1,MyClassmyClass2) |
2 | { |
3 | myClass1.Name= "班级1" ; |
4 | myClass2.Name= "班级2" ; |
5 | } |
1 | container.Resolve<Subject2>(); |
当然这个只是简单的使用,在实际的情况下我们不会这么编写代码,我们不会直接引用对象,而是直接引用接口,这样可以解除代码的耦合性,如下代码:
1 | public Subject2(IClassmyClass1) |
2 | { |
3 | myClass1.Name= "班级1" ; |
4 | } |
1 | public static void ConstructorInjection() |
2 | { |
3 | //container.Resolve<Subject2>(); |
4 |
5 | container.RegisterType<IClass,MyClass>(); |
6 | container.Resolve<Subject2>(); |
7 | } |
这时就需要使用Dependency这个特性类来解决了,在需要特殊指定的依赖关系的参数上加上Dependency特性,并为Dependency指定好参数name(此name参数表示注册对象关系时所指定的名称),代码如下:
1 | public Subject2([Dependency( "your" )] |
2 | IClassclassInfo) |
3 | { |
4 | classInfo.Name= "班级1" ; |
5 | } |
1 | container.RegisterType<IClass,MyClass>() |
2 | .RegisterType<IClass,YourClass>( "your" ); |
3 | container.Resolve<Subject2>(); |
现在还有一个问题,就是当一个类存在多个构造函数的时候,我们如何区分哪个构造函数需要实现注入,哪个不需要?
这时就可以使用InjectionConstructor特性来标识,代码如下:
01 | [InjectionConstructor] |
02 | public Subject2([Dependency( "your" )] |
03 | IClassclassInfo) |
04 | { |
05 | classInfo.Name= "班级1" ; |
06 | } |
07 |
08 | public Subject2(IClassclassInfo1,IClassclassInfo2) |
09 | { |
10 | classInfo1.Name= "班级1" ; |
11 | classInfo2.Name= "班级2" ; |
12 | } |
[b]二、属性注入[/b]
属性注入和构造函数注入类似,只需在需要注入的属性上增加一个Dependency特性,同样的也可以为Dependency指定一个name参数用来指定注入属性的具体对象,如下代码,在Subject属性上增加了Dependency特性,来表示这个属性需要注入:
01 | public class MyClass:IClass |
02 | { |
03 | public MyClass() |
04 | { |
05 | } |
06 |
07 | public void ShowInfo() |
08 | { |
09 | Console.WriteLine( "这个是我的班级" ); |
10 | } |
11 |
12 | [Dependency( "Subject1" )] |
13 | public ISubjectSubject{ get ; set ;} |
14 |
15 | public string Name{ get ; set ;} |
16 |
17 | public string Description{ get ; set ;} |
18 | } |
1 | public static void PropertyInjection() |
2 | { |
3 | container.RegisterType<ISubject,Subject1>( "Subject1" ) |
4 | .RegisterType<IClass,MyClass>(); |
5 | varclassInfo=container.Resolve<IClass>(); |
6 | Console.WriteLine(classInfo.Subject.Name); |
7 | } |
[b]三、方法注入[/b]
方法注入同样只需在需要注入的方法上增加一个特性——InjectionMethod既可(其使用方法也和构造注入类似),这样Unity会自动帮我们完成注入,方法注入和构造注入一样,同样可以在方法的参数上指定Dependency特性来指定参数所依赖的注册,下面的类代码中包含了构造注入、属性注入及方法注入,这边集合在一起展示相对来说直观一些:
01 | public class MyClass:IClass |
02 | { |
03 | public MyClass() |
04 | { |
05 | } |
06 |
07 | public MyClass(ISubjectsubjectInfo) |
08 | { |
09 | this .TempSubject1=subjectInfo; |
10 | } |
11 |
12 | public void ShowInfo() |
13 | { |
14 | Console.WriteLine( "构造注入成功后临时科目1名称:" + this .TempSubject1.Name); |
15 | Console.WriteLine( "属性注入成功后临时科目名称:" + this .Subject.Name); |
16 | Console.WriteLine( "方法注入成功后临时科目2名称:" + this .TempSubject2.Name); |
17 | } |
18 |
19 | [InjectionMethod] |
20 | public void Init(ISubjectsubjectInfo) |
21 | { |
22 | TempSubject2=subjectInfo; |
23 | } |
24 |
25 | [Dependency( "Subject1" )] |
26 | public ISubjectSubject{ get ; set ;} |
27 |
28 | public ISubjectTempSubject1{ get ; set ;} |
29 | public ISubjectTempSubject2{ get ; set ;} |
30 |
31 | public string Name{ get ; set ;} |
32 |
33 | public string Description{ get ; set ;} |
34 | } |
1 | public static void MethodInjection() |
2 | { |
3 | container.RegisterType<ISubject,Subject3>( "Subject1" ) |
4 | .RegisterType<ISubject,Subject4>(); |
5 | container.RegisterType<IClass,MyClass>(); |
6 |
7 | varclassInfo=container.Resolve<IClass>(); |
8 | classInfo.ShowInfo(); |
9 | } |
[b]4、使用配置完成各种注入[/b]
上面所演示的代码都是通过代码来完成对象的注入,下面演示下如何通过配置文件来配置这些注入,具体配置代码如下:
01 | <!--依赖注入配置,包括构造注入,方法注入和属性注入--> |
02 | < alias alias = "IClass" type = "UnityStudyConsole.IDemo.IClass,UnityStudyConsole" /> |
03 | < alias alias = "MyClass" type = "UnityStudyConsole.Demo.MyClass,UnityStudyConsole" /> |
04 | < alias alias = "ISubject" type = "UnityStudyConsole.IDemo.ISubject,UnityStudyConsole" /> |
05 | < alias alias = "Subject3" type = "UnityStudyConsole.Demo.Subject3,UnityStudyConsole" /> |
06 | < alias alias = "Subject4" type = "UnityStudyConsole.Demo.Subject4,UnityStudyConsole" /> |
07 | < container name = "Third" > |
08 | < register type = "IClass" mapTo = "MyClass" > |
09 | < constructor > |
10 | < param name = "subjectInfo" type = "ISubject" > |
11 | < dependency name = "subjectInfo" type = "Subject4" /> |
12 | </ param > |
13 | </ constructor > |
14 | < method name = "Init" > |
15 | < param name = "subjectInfo" type = "ISubject" > |
16 | < dependency name = "subjectInfo" type = "Subject4" /> |
17 | </ param > |
18 | </ method > |
19 | < property name = "Subject" > |
20 | < dependency name = "Subject1" type = "Subject3" /> |
21 | </ property > |
22 | </ register > |
23 | </ container > |
1 | public static void DIConfiguration() |
2 | { |
3 | //获取特定配置节下已命名的配置节<containername="Third">下的配置信息 |
4 | container.LoadConfiguration( "Third" ); |
5 | varclassInfo=container.Resolve<IClass>(); |
6 | classInfo.ShowInfo(); |
7 | } |
[b]5、对已经创建对象进行注入[/b]
一般来说如果想实现依赖注入需要通过Unity容器来进行对象注册,然后通过Unity容器来获取对象,但是如果对象已经存在(就是不是通过Unity容器来获取的对象),这时如何来通过Unity来实现对已有的对象进行依赖注入呢?
Unity容器已经为我们提供好了这种情况的解决办法,就是BuildUp方法,看下下面的代码就能明白了:
01 | public static void BuildUp() |
02 | { |
03 | //事先注册好ISubject和MySubject之间的关系 |
04 | //并指定一个名称以方便在接口中的属性上应用[Dependency("Subject1")]特性 |
05 | //具体请见IDemo.IClass |
06 | container.RegisterType<ISubject,Subject1>( "Subject1" ); |
07 | IClassclassInfo= new MyClass(); |
08 | IClassclassInfo2=container.BuildUp<IClass>(classInfo); |
09 | Console.WriteLine(classInfo2.Subject.Name); |
10 | } |
11 | #endregion |
需要注意的是,与上面所说3种依赖注入的不同的是,上面3中的依赖注入需要在具体的类中使用InjectionConstructor、InjectionMethodDependency和特性,而如果对已经存在的对象进行依赖注入,则需要将InjectionConstructor、InjectionMethod和Dependency写在这个对象实例所实现的接口或父类中,否则会报错!
到本文为止,Unity的各种常用功能都已经介绍完毕了,各位可以下载下面的源代码进行查看,同时也可以通过Main方法中的各个方法来查看Unity的各种功能的使用:
示例代码下载:
(注意:本文示例代码是基于VS2010+Unity2.0,所以请使用VS2010打开,如果没有安装VS2010,请将相关代码复制到相应的VS中运行既可)
[b]微软企业库5.0学习之路系列文章索引:[/b]
扩展学习:
相关文章推荐
- [EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART3——依赖注入
- [EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART4——Unity&PIAB
- (转)[EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART1——为什么要使用Unity?
- [EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART1——为什么要使用Unity?
- [EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(2)
- [EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(2)
- [EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(1)
- (转)[EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(2)
- [EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(1)【转载】
- [EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART5——使用Unity自身的拦截器
- [EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)
- [EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)
- (转)[EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)
- (转)[EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(1)
- 微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(1)
- 微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART5——使用Unity自身的拦截器
- 微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)
- 微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART1——为什么要使用Unity?
- 微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART1——为什么要使用Unity?
- 微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART1——为什么要使用Unity? (转)