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有没有 ...
随机推荐
- HDFS之DataNode
DataNode工作机制 1)一个数据块在datanode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳. 2)DataNode启动后 ...
- Docker (一) 安装 Oracle18c
通过Docker 安装 Oracle18c 1.拉取 oracle18c 镜像 docker pull registry.cn-hangzhou.aliyuncs.com/zhengqing/orac ...
- 新闻实时分析系统-HBase分布式集群部署与设计
HBase是一个高可靠.高性能.面向列.可伸缩的分布式存储系统,利用Hbase技术可在廉价PC Server上搭建 大规模结构化存储集群. HBase 是Google Bigtable 的开源实现,与 ...
- tensorflow的函数
1. if __name__=="__main__": tf.app.run()#运行之前定义的main函数#将传进来的参数,以及flags.FLAGS定义的参数传入到main函数 ...
- Python和Java的区别
这里是我的一些总结,有些是参考别人的(在这里谢谢!!!) 区别: 1.Python比Java简单,学习成本低,开发效率高2.Java运行效率高于Python,尤其是纯Python开发的程序,效率极低3 ...
- 《程序人生》系列-害敖丙差点被开除的P0事故
你知道的越多,你不知道的越多 点赞再看,养成习惯 GitHub https://github.com/JavaFamily上已经收录有一线大厂面试点脑图.个人联系方式和技术交流群,欢迎Star和指教 ...
- 【Android - 控件】之MD - CardView的使用
CardView是Android 5.0新特性——Material Design中的一个布局控件,可以通过属性设置显示一个圆角的类似卡片的视图. 1.CardView的属性: app:cardCorn ...
- AutoCAD二次开发(2020版)--4,使用ARX向导创建编程模板(框架)--
手动创建ObjectARX应用程序非常麻烦,在此步骤中,将介绍ObjectARX向导. 在这里,我们将使用ObjectARX向导创建我们的ObjectARX应用程序. 本节的程序的需求是,接收CAD用 ...
- c# 窗体开发3 文件处理技术
以字节形式向磁盘写入数据通常称为字节流(比特流) 常常使用System.Io 常用的类 类 说明 File 提供用于创建.复制.删除.移动和打开文件的静态方法,并协助创建 FileStream 对象. ...
- jQuery实现倒计时重新发送短信验证码功能示例
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...