2、手写Unity容器--第一层依赖注入
这个场景跟《手写Unity容器--极致简陋版Unity容器》不同,这里构造AndroidPhone的时候,AndroidPhone又依赖于1个IPower,因为打电话没电了需要充电。
一、条件
1、容器--工厂
2、集合
3、反射
4、特性-相当于配置
二、思路
1、RegisterType<TFrom,TTo>()把完整类型名称当作key放入数据字典,把类型当作value放入数据字典方法
2、Resolve<T>(),根据完整类型名称从字典中取出类型
3、得到类型构造函数的参数类型,创建参数类型实例
4、最后创建类型实例
三、代码实现
1、IPhone接口
- namespace SimplestUnity_OneLayer
- {
- interface IPhone
- {
- void Call();
- }
- }
2、AndroidPhone实现
- namespace SimplestUnity_OneLayer
- {
- public class AndroidPhone : IPhone
- {
- public AndroidPhone(IPad iPad)
- {
- Console.WriteLine("{0}构造函数", this.GetType().Name);
- }
- public void Call()
- {
- Console.WriteLine("{0}打电话", this.GetType().Name);
- }
- }
- }
3、IPower接口
- namespace SimplestUnity_OneLayer
- {
- public interface IPower
- {
- /// <summary>
- /// 充电
- /// </summary>
- void ChargeBattery();
- }
- }
4、AndroidPower实现
- namespace SimplestUnity_OneLayer
- {
- public class AndroidPower : IPower
- {
- public AndroidPower()
- {
- Console.WriteLine("{0}构造函数", this.GetType().Name);
- }
- /// <summary>
- /// 充电
- /// </summary>
- public void ChargeBattery()
- {
- Console.WriteLine("充电中{0}", this.GetType().Name);
- }
- }
- }
5、定义1个标记特性DavidInjectionConstructor
- namespace SimplestUnity_OneLayer
- {
- public class DavidInjectionConstructor:Attribute
- {
- }
- }
6、容器--接口
- public interface IDavidContainer
- {
- void RegisterType<TFrom, TTo>();
- T Resolve<T>();
- }
7、容器--实现
- namespace SimplestUnity_OneLayer
- {
- /// <summary>
- /// 容器--工厂
- /// </summary>
- public class DaivdContainer:IDaivdContainer
- {
- private Dictionary<string, Type> containerDictionary = new Dictionary<string, Type>();//字典
- /// <summary>
- /// 注册类型
- /// </summary>
- /// <typeparam name="TFrom"></typeparam>
- /// <typeparam name="TTo"></typeparam>
- public void RegisterType<TFrom, TTo>()
- {
- containerDictionary.Add(typeof(TFrom).FullName, typeof(TTo));
- }
- /// <summary>
- /// 获取实例
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <returns></returns>
- public T Resolve<T>()
- {
- Type type = containerDictionary[typeof(T).FullName];
- //1、得到类型的所有构造函数
- ConstructorInfo[] ctorArray = type.GetConstructors();
- //2、得到有标记DavidInjectionConstructor特性的构造函数,如果都没有标记特性,那么得到参数最多的构造函数
- ConstructorInfo currentCtor = null;
- if (ctorArray.Count(c => c.IsDefined(typeof(DavidInjectionConstructor), true)) > )
- {
- currentCtor = ctorArray.FirstOrDefault(c => c.IsDefined(typeof(DavidInjectionConstructor), true));//得到第1个标记DavidInjectionConstructor特性的构造函数
- }
- else
- {
- currentCtor = ctorArray.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();//得到参数个数最多的构造函数
- }
- List<object> paraList = new List<object>();
- foreach (var para in currentCtor.GetParameters())
- {
- //得到的参数类型是IPower,抽象无法创建实例
- var paraType = para.ParameterType;
- //所以根据IPower Key,得到AndroidPower类型,具体类型就可以创建实例
- var targetParaType = containerDictionary[paraType.FullName];
- paraList.Add(Activator.CreateInstance(targetParaType));
- }
- return (T)Activator.CreateInstance(type,paraList.ToArray());
- }
- }
- }
8、客户端调用
- namespace SimplestUnity_OneLayer
- {
- class Program
- {
- static void Main(string[] args)
- {
- DaivdContainer davidContainer = new DaivdContainer();
- davidContainer.RegisterType<IPhone, AndroidPhone>();
- davidContainer.RegisterType<IPower, AndroidPower>();
- IPhone iphone = davidContainer.Resolve<IPhone>();
- iphone.Call();
- }
- }
- }
9、运行效果
2、手写Unity容器--第一层依赖注入的更多相关文章
- 3、手写Unity容器--第N层依赖注入
这个场景跟<手写Unity容器--第一层依赖注入>又不同,这里构造AndroidPhone的时候,AndroidPhone依赖于1个IPad,且依赖于1个IHeadPhone,而HeadP ...
- 1、手写Unity容器--极致简陋版Unity容器
模拟Unity容器实例化AndroidPhone 思路: 1.注册类型:把类型完整名称作为key添加到数据字典中,类型添加到数据字典的value中 2.获取实例:根据完整类型名称也就是key取出val ...
- 30个类手写Spring核心原理之依赖注入功能(3)
本文节选自<Spring 5核心原理> 在之前的源码分析中我们已经了解到,依赖注入(DI)的入口是getBean()方法,前面的IoC手写部分基本流程已通.先在GPApplicationC ...
- 手写web框架之实现依赖注入功能
我们在Controller中定义了Service成员变量,然后在Controller的Action方法中调用Service成员变量的方法,那么如果实现Service的成员变量? 之前定义了@Injec ...
- Mybatis(一):手写一套持久层框架
作者 : 潘潘 未来半年,有幸与导师们一起学习交流,趁这个机会,把所学所感记录下来. 「封面图」 自毕业以后,自己先创业后上班,浮沉了近8年,内心着实焦躁,虽一直是走科班路线,但在技术道路上却始终没静 ...
- 如何把对象手动注入Spring容器并实现依赖注入
将对象注入到Spring容器并实现依赖注入 public class UserDao { @Resource AccountService accountService; public void pr ...
- [转载]Spring下IOC容器和DI(依赖注入) @Bean及@Autowired
Spring下IOC容器和DI(依赖注入) @Bean及@Autowired自动装配 bean是什么 bean在spring中可以理解为一个对象.理解这个对象需要换一种角度,即可将spring看做一门 ...
- 手写IOC容器
IOC(控制翻转)是程序设计的一种思想,其本质就是上端对象不能直接依赖于下端对象,要是依赖的话就要通过抽象来依赖.这是什么意思呢?意思就是上端对象如BLL层中,需要调用下端对象的DAL层时不能直接调用 ...
- 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖
本次博客的目标 1. 手写spring循环依赖的整个过程 2. spring怎么解决循环依赖 3. 为什么要二级缓存和三级缓存 4. spring有没有解决构造函数的循环依赖 5. spring有没有 ...
随机推荐
- JAVA中字符串常见操作
String str1="hello,world";String str2="Hello,World"; 1.字符串的比较:例,System.out.print ...
- 为什么阿里巴巴Java开发手册中强制要求不要在foreach循环里进行元素的remove和add操作?
在阅读<阿里巴巴Java开发手册>时,发现有一条关于在 foreach 循环里进行元素的 remove/add 操作的规约,具体内容如下: 错误演示 我们首先在 IDEA 中编写一个在 f ...
- LESSON 5 - Markov Sources
1. Markov sources The state of the Markov chain is used to represent the “memory” of the source ...
- 相对和绝对路径、cd命令、创建和删除目录、rm命令 使用介绍
第2周第1次课(3月26日) 课程内容:2.6 相对和绝对路径2.7 cd命令2.8 创建和删除目录mkdir/rmdir2.9 rm命令 2.6相对和绝对路径 任何一个文件都有一个从根开始的路径,绝 ...
- 一张图讲解单机FastDFS图片服务器安装步骤(修订版)
前面已经讲 一张图秒懂微服务的网络架构,通过此文章可以了解FastDFS组件中单机安装流程. 单机版架构图 以下为单机FastDFS安装步骤 一.环境准备 CentOS 7.X libfastcomm ...
- MySQL必知必会(通配符过滤Like,%,_)
SELECT prod_id, prod_name FROM products WHERE prod_name LIKE 'jet%'; #百分号(%)表示任何字符出现任意次数, %不能匹配值为NUL ...
- WeihanLi.Npoi 支持 ShadowProperty 了
WeihanLi.Npoi 支持 ShadowProperty 了 Intro 在 EF 里有个 ShadowProperty (阴影属性/影子属性)的概念,你可以通过 FluentAPI 的方式来定 ...
- idea建立项目关联到git仓库操作步骤
eg:创建一个名为demo的git项目 创建git远程项目,命名为[/demo] 在[D:\workspace\gf]创建本地项目[demo] 在idea里选择[VCS]->[Checkout ...
- AntV G2 图表tooltip重命名
在做数据可视化的过程中,遇到了一个问题,就是给图表tooltip重命名. 在研究后,发现了三种方法: 方法1:一般情况下,可以在给chart绑定数据源时,添加scale配置,并在scale配置中设置别 ...
- mac+chrome 最常用快捷键
12个mac快捷键 命令 含义 command+空格 (先摁command再摁空格) Spotlight搜索 crt+command+F 最大化和关闭最大化切换 Command+H 隐藏当前窗口 Co ...