继续学习Unity,在前几篇中已经将Unity的使用方法做了一个还算详细的介绍了,主要是如何通过代码及配置文件来注册对象之间的关系、Unity内置所有的生命周期管理使用介绍,及Unity的Register和Resolve的一些高级应用。通过在PART1——为什么要使用Unity?的学习我们知道Unity可以帮我们简化并管理对象之间的关系(也就是前几篇所介绍的),而今天则要介绍Unity的另外一个重要功能——DI(依赖注入)。

本篇文章将主要介绍:

1、构造函数注入。

2、属性注入。

3、方法注入。

4、使用配置完成各种注入。

5、对已经创建对象进行注入。

一、构造函数注入

在有些时候,我们所编写的类中的构造函数都会包含对其他对象的引用,如下代码:

public Subject2(MyClass myClass1,MyClass myClass2)
{
myClass1.Name = "班级1";
myClass2.Name = "班级2";
}

可以看到这个构造函数有2个参数,都依赖于MyClass类,如果一般情况下想要调用,我们总是需要实现构建好2个myclass对象,所以相对来说比较麻烦,而如果使用Unity来调用就会方便许多,如下代码:

container.Resolve<Subject2>();

仅仅一行既可,Unity容器会自动帮我们构建好所需的依赖对象实例。

当然这个只是简单的使用,在实际的情况下我们不会这么编写代码,我们不会直接引用对象,而是直接引用接口,这样可以解除代码的耦合性,如下代码:

public Subject2(IClass myClass1)
{
myClass1.Name = "班级1";
}

这样Subject2类的构造函数仅仅依赖于IClass接口,并依赖于具体的实现类,这种情况下,如果想调用的话,需要实现注册好对象之间的关系,如下代码:

public static void ConstructorInjection()
{
//container.Resolve<Subject2>(); container.RegisterType<IClass, MyClass>();
container.Resolve<Subject2>();
}

通过Unity容器对象的获取对象时候默认总是获取非命名默认注册对象,但是如果调用Subject2的构造函数参数我想指定具体的对象时怎么办?

这时就需要使用Dependency这个特性类来解决了,在需要特殊指定的依赖关系的参数上加上Dependency特性,并为Dependency指定好参数name(此name参数表示注册对象关系时所指定的名称),代码如下:

public Subject2([Dependency("your")]
IClass classInfo)
{
classInfo.Name = "班级1";
}

调用代码:

container.RegisterType<IClass, MyClass>()
.RegisterType<IClass, YourClass>("your");
container.Resolve<Subject2>();

可以看到,我对IClass注册了2个对象,而我在Subject2的构造函数参数上使用了Dependency特性指定了ClassInfo参数获取注册名为“your”的对象。

现在还有一个问题,就是当一个类存在多个构造函数的时候,我们如何区分哪个构造函数需要实现注入,哪个不需要?

这时就可以使用InjectionConstructor特性来标识,代码如下:

[InjectionConstructor]
public Subject2([Dependency("your")]
IClass classInfo)
{
classInfo.Name = "班级1";
} public Subject2(IClass classInfo1, IClass classInfo2)
{
classInfo1.Name = "班级1";
classInfo2.Name = "班级2";
}

Unity只会调用标识了InjectionConstructor特性的构造函数,这样就很好的解决了多构造函数的情况下,Unity调用哪个构造函数。

二、属性注入

属性注入和构造函数注入类似,只需在需要注入的属性上增加一个Dependency特性,同样的也可以为Dependency指定一个name参数用来指 定注入属性的具体对象,如下代码,在Subject属性上增加了Dependency特性,来表示这个属性需要注入:

public class MyClass : IClass
{
public MyClass()
{
} public void ShowInfo()
{
Console.WriteLine("这个是我的班级");
} [Dependency("Subject1")]
public ISubject Subject { get; set; } public string Name { get; set; } public string Description { get; set; }
}

具体的调用代码:

public static void PropertyInjection()
{
container.RegisterType<ISubject, Subject1>("Subject1")
.RegisterType<IClass,MyClass>();
var classInfo = container.Resolve<IClass>();
Console.WriteLine(classInfo.Subject.Name);
}

这样ClassInfo的Subject属性自动关联到了Subject1类上(完成了属性注入),访问classInfo.Subject.Name可以得到“科目1”。

三、方法注入

方法注入同样只需在需要注入的方法上增加一个特性——InjectionMethod既可(其使用方法也和构造注入类似),这样Unity会自动帮我们完成注入,方法注入和构造注入一样,同样可以在方法的参数上指定Dependency特性来指定参数所依赖的注册,下面的类代码中包含了构造注入、属性注入及方法注入,这边集合在一起展示相对来说直观一些:

public class MyClass : IClass
{
public MyClass()
{
} public MyClass(ISubject subjectInfo)
{
this.TempSubject1 = subjectInfo;
} public void ShowInfo()
{
Console.WriteLine("构造注入成功后临时科目1名称:" + this.TempSubject1.Name);
Console.WriteLine("属性注入成功后临时科目名称:" + this.Subject.Name);
Console.WriteLine("方法注入成功后临时科目2名称:" + this.TempSubject2.Name);
} [InjectionMethod]
public void Init(ISubject subjectInfo)
{
TempSubject2 = subjectInfo;
} [Dependency("Subject1")]
public ISubject Subject { get; set; } public ISubject TempSubject1 { get; set; }
public ISubject TempSubject2 { get; set; } public string Name { get; set; } public string Description { get; set; }
}

具体的调用代码:

public static void MethodInjection()
{
container.RegisterType<ISubject, Subject3>("Subject1")
.RegisterType<ISubject, Subject4>();
container.RegisterType<IClass, MyClass>(); var classInfo = container.Resolve<IClass>();
classInfo.ShowInfo();
}

效果图如下:

4、使用配置完成各种注入

上面所演示的代码都是通过代码来完成对象的注入,下面演示下如何通过配置文件来配置这些注入,具体配置代码如下:

<!--依赖注入配置,包括构造注入,方法注入和属性注入-->
<alias alias="IClass" type="UnityStudyConsole.IDemo.IClass, UnityStudyConsole" />
<alias alias="MyClass" type="UnityStudyConsole.Demo.MyClass, UnityStudyConsole" />
<alias alias="ISubject" type="UnityStudyConsole.IDemo.ISubject, UnityStudyConsole" />
<alias alias="Subject3" type="UnityStudyConsole.Demo.Subject3, UnityStudyConsole" />
<alias alias="Subject4" type="UnityStudyConsole.Demo.Subject4, UnityStudyConsole" />
<container name="Third">
<register type="IClass" mapTo="MyClass">
<constructor>
<param name="subjectInfo" type="ISubject">
<dependency name="subjectInfo" type="Subject4"/>
</param>
</constructor>
<method name="Init">
<param name="subjectInfo" type="ISubject">
<dependency name="subjectInfo" type="Subject4"/>
</param>
</method>
<property name="Subject">
<dependency name="Subject1" type="Subject3"/>
</property>
</register>
</container>

代码如下:

public static void DIConfiguration()
{
//获取特定配置节下已命名的配置节<container name="Third">下的配置信息
container.LoadConfiguration("Third");
var classInfo = container.Resolve<IClass>();
classInfo.ShowInfo();
}

具体的效果是和上面截图中是一样的,只不过这边的依赖注入是通过配置文件来实现的。

5、对已经创建对象进行注入

一般来说如果想实现依赖注入需要通过Unity容器来进行对象注册,然后通过Unity容器来获取对象,但是如果对象已经存在(就是不是通过Unity容器来获取的对象),这时如何来通过Unity来实现对已有的对象进行依赖注入呢?

Unity容器已经为我们提供好了这种情况的解决办法,就是BuildUp方法,看下下面的代码就能明白了:

public static void BuildUp()
{
//事先注册好ISubject和MySubject之间的关系
//并指定一个名称以方便在接口中的属性上应用[Dependency("Subject1")]特性
//具体请见IDemo.IClass
container.RegisterType<ISubject, Subject1>("Subject1");
IClass classInfo = new MyClass();
IClass classInfo2 = container.BuildUp<IClass>(classInfo);
Console.WriteLine(classInfo2.Subject.Name);
}
#endregion

在上面的代码中,已经创建好一个对象实例了,这时只需将这个对象作为参数放入BuildUp中,同时还需指定这个对象实例所实现的接口或父类类型,这样Unity就会自动帮我们将这个已存在对象实例中各种注入。

需要注意的是,与上面所说3种依赖注入的不同的是,上面3中的依赖注入需要在具体的类中使用InjectionConstructor、 InjectionMethodDependency和特性,而如果对已经存在的对象进行依赖注入,则需要将InjectionConstructor、 InjectionMethod和Dependency写在这个对象实例所实现的接口或父类中,否则会报错!

到本文为止,Unity的各种常用功能都已经介绍完毕了,各位可以下载下面的源代码进行查看,同时也可以通过Main方法中的各个方法来查看Unity的各种功能的使用:

示例代码下载:点我下载

使用Unity解耦你的系统—PART3——依赖注入的更多相关文章

  1. 使用Unity解耦你的系统—PART4——Unity&PIAB

    在前面几篇有关Unity学习的文章中,我对Unity的一些常用功能进行介绍,包括:Unity的基本知识.管理对象之间的关系.生命周期.依赖注入等,今天则是要介绍Unity的另外一个重要功能——拦截(I ...

  2. Unity文档阅读 第二章 依赖注入

    Introduction 介绍Chapter 1 outlines how you can address some of the most common requirements in enterp ...

  3. 【Unity】微软的一款依赖注入组件

    前言 前面学习了autofac这个依赖注入组件,本来是打算写在一起的,因为这个组件没打算像autofac一样详细的写,只是写下以前自己鼓捣玩搭建框架然后使用的一个依赖注入组件,并且也是进行了封装使用. ...

  4. 微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)

    今天继续介绍Unity,在上一篇的文章中,我介绍了使用UnityContainer来注册对象之间的关系.注册已存在的对象之间的关系,同时着重介绍 了Unity内置的各种生命周期管理器的使用方法,今天则 ...

  5. 使用Unity 实现ASP.NET Web API 依赖注入

    DI/IoC 的设计前面已经讲过好几次了,简单的一段话说明就是:「目标对象与外部相依的方式仅相依于 interface,而相依 interface 的 instance 透过 constructor ...

  6. [.NET] 使用Json.NET提供依赖注入功能(Dependence Injection)

    [.NET] 使用Json.NET提供依赖注入功能(Dependence Injection) 前言 在一些小型项目的开发情景里,系统不需要大型DI Framework所提供的:单一对象生成.生命周期 ...

  7. IOC使用Unity 实现依赖注入

    转自:http://www.cnblogs.com/techborther/archive/2012/01/06/2313498.html http://www.cnblogs.com/xishuai ...

  8. 理解依赖注入(IOC)和学习Unity

    资料1: IOC:英文全称:Inversion of Control,中文名称:控制反转,它还有个名字叫依赖注入(Dependency Injection). 作用:将各层的对象以松耦合的方式组织在一 ...

  9. 依赖注入与Unity(一) 介绍

        在你学习依赖注入和Unity之前,你需要明白你为什么要使用它们.为了明白为什么要使用它们,你应该明白依赖注入和Unity能够帮助你解决什么类型的问题.作为介绍部分,这一章不会涉及太多关于Uni ...

随机推荐

  1. redis 字符串的管理的一点理解

    redis字符串可以实现通过地址偏移找到所在结构体的首地址,struct sdshdr *sh = (void *)(s - (sizeof(struct sdshdr))) 也就是通过buf地址可以 ...

  2. Qt ------ 判断运行在何种系统下

    #ifdef Q_OS_WIN // Windows上的代码 #endif #ifdef Q_OS_LINUX // Linux上的代码 #endif #ifdef Q_OS_MAC // Mac上的 ...

  3. Kubernetes Deployment滚动升级

    我们k8s集群使用的是1.7.7版本的,该版本中官方已经推荐使用Deployment代替Replication Controller(rc)了,Deployment继承了rc的全部功能外,还可以查看升 ...

  4. 前端PHP入门-013-变量作用域

    目前,我们知道了几个不同的规矩: 函数定义时后括号里面接的变量是形式上的参数(形参),与函数体外的变量没有任何关系.仅仅是在函数内部执行 函数内声明的变量也与函数外的变量没关系. 但是,我们实际的处理 ...

  5. TersorflowTutorial_MNIST数据集上简单CNN实现

    MNIST数据集上简单CNN实现 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 Tensorflow机器学习实战指南 源代码请点击下方链接欢迎加星 Tesorflow实现基于MNI ...

  6. Jenkins使用教程之用户权限管理(包含插件的安装)

    在工作的过程中由于分工合作的关系,我们因为工作内容的不同可能分为不同的组织里,但是jenkins默认的权限管理并没有用户组的概念,所以我们需要第三方插件的支持来解决问题.插件:Role-based A ...

  7. 重构改善既有代码设计--重构手法18:Self Encapsulate Field (自封装字段)

    你直接访问一个值域(field),但与值域之间的耦合关系逐渐变得笨拙. 为这个值域建立取值/设值函数(getting/setting methods),并且只以这些函数来访问值域. private i ...

  8. 【BZOJ】2337: [HNOI2011]XOR和路径 期望+高斯消元

    [题意]给定n个点m条边的带边权无向连通图(有重边和自环),在每个点随机向周围走一步,求1到n的期望路径异或值.n<=100,wi<=10^9. [算法]期望+高斯消元 [题解]首先异或不 ...

  9. 下载Google My Tracks

    http://code.google.com/p/mytracks/source/browse/?name=2.0.2#hg%2FMyTracks%253Fstate%253Dclosed 需要类似的 ...

  10. a 标签传值

    转载:http://blog.csdn.net/muyeju/article/details/48594377 .<a>标签传值的形式--参数固定:<a href="地址? ...