C# 一个初学者对 依赖注入 IOC 的理解( 含 Unity 的使用)
通过 人打电话 来谈谈自己对IOC的理解
版本1.0
public class Person
{
public AndroidPhone Phone { get; set; }
public void CallForSomebody()
{
Phone.Call();
}
}
public class AndroidPhone
{
public void Call()
{
Console.WriteLine($"{this.GetType().Name} is calling");
}
}
class Program
{
static void Main(string[] args)
{
Person person = new Person
{
Phone = new AndroidPhone()
};
person.CallForSomebody();
Console.ReadKey();
}
}
如果这时候,想给这个人一部苹果手机,那么必须要修改 Person 类, 将属性Phone的类型改成:ApplePhone.这显然违背了OOP思想的"对修改封闭,对扩展开放"原则.同时该代码也不符合"接口分离原则",于是乎做如下调整.
版本2.0
public class Person
{
//定义 Phone 为 接口 IPhone 类型
public IPhone Phone { get; set; }
public void CallForSomebody()
{
Phone.Call();
}
}
public interface IPhone
{
void Call();
}
public class ApplePhone : IPhone
{
public void Call()
{
Console.WriteLine($"{this.GetType().Name} is calling");
}
}
public class AndroidPhone : IPhone
{
public void Call()
{
Console.WriteLine($"{this.GetType().Name} is calling");
}
}
控制台程序:
Person person = new Person();
//给这个人一部安卓手机
person.Phone = new AndroidPhone();
person.CallForSomebody();
//给这个人一部苹果手机
person.Phone = new ApplePhone();
person.CallForSomebody();
如果需要给诺基亚手机,只需要在创建一个诺基亚Phone类,实现 IPhone 接口,而不需要修改底层代码.
依赖注入有三种方式:
public class Person
{
//属性注入
public IPhone Phone { get; set; }
//构造函数注入
public Person(IPhone phone)
{
this.Phone = phone;
}
//方法注入
public void MethodInject(IPhone phone)
{
this.Phone = phone;
}
public void CallForSomebody()
{
Phone.Call();
}
}
版本2.0虽然不需要修改底层代码,但是控制台的代码依然需要修改,我们需要将 new AndridPhone() 更改成 new ApplePhone()
版本3.0 ( 利用 Unity )
学习新东西都是从 hello world 开始,先来一段 Unity 的 hello world
//创建一个IOC容器
IUnityContainer container = new UnityContainer();
//想要安卓手机就注册安卓手机
//container.RegisterType<IPhone, AndroidPhone>();
//想要苹果手机就注册苹果手机
container.RegisterType<IPhone, ApplePhone>();
IPhone phone = container.Resolve<IPhone>();
Person person = new Person(phone);
person.CallForSomebody();
这段代码其实 跟 版本2.0没什么区别,甚至还复杂了,版本2.0是改 new AndroidPhone() , 这里是改 container.RegisterType<IPhone, AndroidPhone>()
版本4.0
新建一个配置文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<containers>
<container name="unityContainer">
<!--type,mapTo:逗号左边是类的完全限定名,即命名空间+类名;逗号右边是程序集名称-->
<register type="IOCUnity.IPhone,IOCUnity" mapTo="IOCUnity.AndroidPhone,IOCUnity"></register>
</container>
</containers>
</unity>
</configuration>
控制台代码如下:
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap
{
ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + @"UnityXml\UnityConfig.xml")
};
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap,ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
IUnityContainer container = new UnityContainer();
section.Configure(container, "unityContainer");
IPhone phone = container.Resolve<IPhone>();
Person person = new Person(phone);
person.CallForSomebody();
如果要换成 ApplePhone , 只需要将 配置文件中 mapTo="IOCUnity.AndroidPhone,IOCUnity" 更改成 mapTo="IOCUnity.ApplePhone,IOCUnity"> 即可,源代码不需要做任何修改
版本4.5
配置文件修改: 添加 name 标记
<register type="IOCUnity.IPhone,IOCUnity" mapTo="IOCUnity.ApplePhone,IOCUnity" name="Apple"></register>
<register type="IOCUnity.IPhone,IOCUnity" mapTo="IOCUnity.AndroidPhone,IOCUnity" name="Android"></register>
//创建一个安卓手机
//IPhone phone = container.Resolve<IPhone>("Android");
//创建一个苹果手机
IPhone phone = container.Resolve<IPhone>("Android");
版本5.0
控制台代码:
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap
{
ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + @"UnityXml\UnityConfig.xml")
};
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
IUnityContainer container = new UnityContainer();
section.Configure(container, "unityContainer");
Person person = container.Resolve<Person>();
/*
上面创建了一个person,虽然我们没有给它的属性Phone赋值,但实际上 Unity 已经帮我们注入了.
Unity 有三种特性 分别对应三种注入方式:
[InjectionConstructor] 构造函数注入
[dependency] 属性注入
[InjectionMethod] 方法注入
如果一个特性都不打,那么Unity 默认会采用 构造函数注入,并且是选用入参最多的那个构造函数注入.因此,推荐采用 构造函数注入,因为它是无侵入式的,不需要打任何特性.
*/
person.CallForSomebody();
public class Person
{
//属性注入
[Dependency]
public IPhone Phone { get; set; }
//构造函数注入
[InjectionConstructor]
public Person(IPhone phone)
{
this.Phone = phone;
}
//方法注入
[InjectionMethod]
public void MethodInject(IPhone phone)
{
this.Phone = phone;
}
public void CallForSomebody()
{
Phone.Call();
}
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<containers>
<container name="unityContainer">
<!--type,mapTo:逗号左边是类的完全限定名,即命名空间+类名;逗号右边是程序集名称-->
<register type="IOCUnity.IPhone,IOCUnity" mapTo="IOCUnity.ApplePhone,IOCUnity"></register>
<register type="IOCUnity.Person,IOCUnity" mapTo="IOCUnity.Person,IOCUnity"></register>
</container>
</containers>
</unity>
</configuration>
C# 一个初学者对 依赖注入 IOC 的理解( 含 Unity 的使用)的更多相关文章
- 控制反转(Inversion of Control,英文缩写为IoC),另外一个名字叫做依赖注入(Dependency Injection,简称DI)
控制反转(Inversion of Control,英文缩写为IoC),另外一个名字叫做依赖注入(Dependency Injection,简称DI),是一个重要的面向对象编程的法则来削减计算机程序的 ...
- android使用篇(四) 注解依赖注入IOC实现绑定控件
在android使用篇(三) MVC模式中提到一个问题: 1) 视图层(View):一般採用XML文件进行界面的描写叙述,使用的时候能够很方便的引入,可是用xml编写了,又须要在Acitvity声明而 ...
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之九 || 依赖注入IoC学习 + AOP界面编程初探
更新 1.如果看不懂本文,或者比较困难,先别着急问问题,我单写了一个关于依赖注入的小Demo,可以下载看看,多思考思考注入的原理: https://github.com/anjoy8/BlogArti ...
- Z从壹开始前后端分离【 .NET Core2.2/3.0 +Vue2.0 】框架之九 || 依赖注入IoC学习 + AOP界面编程初探
本文梯子 本文3.0版本文章 更新 代码已上传Github+Gitee,文末有地址 零.今天完成的绿色部分 一.依赖注入的理解和思考 二.常见的IoC框架有哪些 1.Autofac+原生 2.三种注入 ...
- TypeC一个微软开发的超简单.NET依赖注入/IoC容器
控制反转(IoC,Inversion of Control)是由Martin Fowler总结出来的一种设计模式,用来减少代码间的耦合.一般而言,控制反转分为依赖注入(Dependency Injec ...
- 关于依赖注入IOC/DI的感想
之前一直不明白依赖注入有什么好处,甚至觉得它是鸡肋,现在想想,当时真是可笑. 这个想法正如同说接口是没有用处一样. 当整个项目非常庞大,各个方法之间的调用非常复杂,那么,可以想象一下,假设说没有任何的 ...
- DI依赖注入/IOC控制反转
DI依赖注入# 啥都不说,直接上代码 <?php class UserController { private $user; function __construct(UserModel $us ...
- 大话DI依赖注入+IOC控制反转(二) 之 浅析.Net Core中的DI与IOC
转发时请注明原创作者及地址,否则追究责任.原创:alunchen 在上一篇文章中,我们聊了很多关于定义的方面,比较孤燥,下面我们结合.Net Core聊一下依赖注入&控制反转. 三种对象生 ...
- 大话DI依赖注入+IOC控制反转(一) 之 定义
转发时请注明原创作者及地址,否则追究责任.原创:alunchen 依赖注入与控制反转 依赖注入与控制反转是老生常谈的问题.一般面试也会面试到这种问题.网上很多很多这方面的资料,搜索出来一大堆 ...
随机推荐
- 基于socket实现的简单的聊天程序
记得八年前第一次使用socket做的一个五子棋程序,需要序列化棋子对象,传递到对方的电脑上. 一个偶然的机会,第二次使用socket做点事情.先看聊天服务器端的实现: 服务器端要实现以下功能: ...
- mac 上传本地代码到 Github 教程
网上有很多关于windows系统上传本地代码到github的文章,但是自己用的是mac,在网上也找了相关文章,实践的过程中还是遇到了很多问题,现在把自己的成功实践分享出来,希望能对大家有帮助. 1.首 ...
- Qt 创建一个QtDesinger第三方控件
1.需要创建一个合适的.pro文件 2.创建一个继承QDesignerCustomWidgetInterface的类,描述控件的一些属性. 函数 描述和返回值 name() 指定控件的名称 group ...
- 题目1031:xxx定律
题目描述: 对于一个数n,如果是偶数,就把n砍掉一半:如果是奇数,把n变成 3*n+ 1后砍掉一半,直到该数变为1为止. 请计算需要经过几步才能将n变到1,具体可见样例. 输入: 测试包含多个用例,每 ...
- JS离开页面 弹窗
function bindDOMEvents() { $(document).keydown(function (e) { var key = e.which || e.keyCode; if (ke ...
- Object源码解析(JDK1.8)
package java.lang; public class Object { /** * 一个本地方法,具体是用C(C++)在DLL中实现的,然后通过JNI调用 */ private static ...
- [总结] O(n)求和为0的最长子段
以这题为例 Solution 我们首先用前缀和差分,可以认为G是1,R是-1,然后求一个前缀和qzh. 如果 qzh[i]==qzh[j] 那么 i~j 这一整段,一定是一个和为0的区间,即红绿相等的 ...
- 有关Redis的Add和Set方法的比较
测试发现,如果key已经存在,则调用Redis.Add(key, value)则不能添加或修改此key的内容value: 这样的话,我们在添加一个key和value的时候,不得不判断一次Contain ...
- Node的前端化工具
1.页面实时更新 browser-sync start --server --files "css/*.css, *.html,js/*.js"
- spring-boot 多模块化项目和EurekaServer的搭建
Spring boot由于其 1.易于开发和维护.2.单个微服务启动快.3.局部修改部署容易.4.技术栈不受语言限制等优点受到越来越多公司的重视.spring-boot还集成了许多关于微服务开发的框架 ...