3、手写Unity容器--第N层依赖注入
这个场景跟《手写Unity容器--第一层依赖注入》又不同,这里构造Student的时候,Student依赖于1个Teacher,Teacher又依赖于1个Computer,而Computer又依赖于Power
链式依赖
一、条件
1、容器--工厂
2、集合
3、反射
4、特性-相当于配置(为什么相当于配置呢?因为假设Teacher有多个构造函数,不知道构造哪一个,所以需要标记出来)
二、思路
1、注册类型:RegisterType<TFrom,TTo>(),把类型的完整类型名称当作key放入数据字典,把类型当作value放入数据字典。
2、获取实例:Resolve<T>(),根据完整类型名称从字典中取出类型
3、得到类型构造函数的参数类型,递归创建参数类型实例,递归:隐形的跳出条件,条件就是GetParameters结果为空,targetType拥有无参数构造函数
4、最后再创建类型实例
三、代码实现
1、IStudent接口
- namespace SimplestUnity_nLayer.Interface
- {
- interface IStudent
- {
- /// <summary>
- /// 学习
- /// </summary>
- void Study();
- }
- }
2、Students接口实现
- namespace SimplestUnity_nLayer
- {
- class Student:IStudent
- {
- [DavidInjectionConstructor]
- public Student(ITeacher iTeacher)
- {
- Console.WriteLine("{0}构造函数", this.GetType().Name);
- }
- /// <summary>
- /// 学习
- /// </summary>
- public void Study()
- {
- Console.WriteLine("{0}学习", this.GetType().Name);
- }
- }
- }
3、ITeacher接口
- namespace SimplestUnity_nLayer
- {
- interface ITeacher
- {
- /// <summary>
- /// 教学
- /// </summary>
- void Teach();
- }
- }
4、Teacher实现
- namespace SimplestUnity_nLayer
- {
- class Teacher:ITeacher
- {
- [DavidInjectionConstructor]
- public Teacher(IComputer iComputer)
- {
- Console.WriteLine("{0}构造函数", this.GetType().Name);
- }
- /// <summary>
- /// 教学
- /// </summary>
- public void Teach()
- {
- Console.WriteLine("{0}教学", this.GetType().Name);
- }
- }
- }
5、IComputer接口
- namespace SimplestUnity_nLayer
- {
- interface IComputer
- {
- /// <summary>
- /// 显示
- /// </summary>
- void Show();
- }
- }
6、Computer实现
- namespace SimplestUnity_nLayer
- {
- class Computer: IComputer
- {
- [DavidInjectionConstructor]
- public Computer(IPower iPower)
- {
- Console.WriteLine("{0}构造函数", this.GetType().Name);
- }
- /// <summary>
- /// 显示
- /// </summary>
- public void Show()
- {
- Console.WriteLine("{0}显示", this.GetType().Name);
- }
- }
- }
7、IPower接口
- namespace SimplestUnity_nLayer
- {
- interface IPower
- {
- /// <summary>
- /// 充电
- /// </summary>
- void ChargeBattery();
- }
- }
8、Power实现
- namespace SimplestUnity_nLayer
- {
- public class Power : IPower
- {
- [DavidInjectionConstructor]
- public Power()
- {
- Console.WriteLine("{0}构造函数", this.GetType().Name);
- }
- /// <summary>
- /// 充电
- /// </summary>
- public void ChargeBattery()
- {
- Console.WriteLine("充电中{0}", this.GetType().Name);
- }
- }
- }
9、容器--接口
- namespace SimplestUnity_nLayer
- {
- public interface IDaivdContainer
- {
- /// <summary>
- /// 注册类型
- /// </summary>
- /// <typeparam name="TFrom"></typeparam>
- /// <typeparam name="TTo"></typeparam>
- void RegisterType<TFrom, TTo>();
- /// <summary>
- /// 获取实例
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <returns></returns>
- T Resolve<T>();
- }
- }
10、容器--实现
- namespace SimplestUnity_nLayer
- {
- /// <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];
- return (T)this.CreateInstance(type);
- }
- private object CreateInstance(Type type)
- {
- //1、得到类型的所有构造函数
- ConstructorInfo[] ctorArray = type.GetConstructors();
- //2、得到有标记DavidInjectionConstructor特性的构造函数,如果都没有标记特性,那么得到参数最多的构造函数
- ConstructorInfo currentCtor = null;
- if (ctorArray.Count(c => c.IsDefined(typeof(DavidInjectionConstructor), true)) > )
- {
- //得到第1个标记DavidInjectionConstructor特性的构造函数
- currentCtor = ctorArray.FirstOrDefault(c => c.IsDefined(typeof(DavidInjectionConstructor), true));
- }
- else
- {
- //得到参数个数最多的构造函数
- currentCtor = ctorArray.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();
- }
- List<object> paraList = new List<object>();
- //递归:隐形的跳出条件,条件就是GetParameters结果为空,targetType拥有无参数构造函数
- foreach (var para in currentCtor.GetParameters())
- {
- //得到的参数类型是IPower,抽象无法创建实例
- var paraType = para.ParameterType;
- //所以根据IPower Key,得到Power类型,具体类型就可以创建实例
- var targetParaType = containerDictionary[paraType.FullName];
- //继续检查targetParaType的构造函数,不能直接创建实例了
- Object obj = this.CreateInstance(targetParaType);
- paraList.Add(obj);
- }
- return Activator.CreateInstance(type, paraList.ToArray());
- }
- }
- }
11、标记特性--配置
- namespace SimplestUnity_nLayer
- {
- public class DavidInjectionConstructor:Attribute
- {
- }
- }
12、客户端调用
- using SimplestUnity_nLayer.Interface;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace SimplestUnity_nLayer
- {
- class Program
- {
- static void Main(string[] args)
- {
- DaivdContainer davidContainer = new DaivdContainer();
- davidContainer.RegisterType<IStudent, Student>();
- davidContainer.RegisterType<ITeacher, Teacher>();
- davidContainer.RegisterType<IComputer, Computer>();
- davidContainer.RegisterType<IPower, Power>();
- IStudent iStudent = davidContainer.Resolve<IStudent>();
- iStudent.Study();
- }
- }
- }
13、运行效果
构建学生的时候先构建了电源,后构建了电脑,其次构建了老师,最后才构建出学生。
14、项目截图
3、手写Unity容器--第N层依赖注入的更多相关文章
- 2、手写Unity容器--第一层依赖注入
这个场景跟<手写Unity容器--极致简陋版Unity容器>不同,这里构造AndroidPhone的时候,AndroidPhone依赖于1个IPad 1.IPhone接口 namespac ...
- 1、手写Unity容器--极致简陋版Unity容器
模拟Unity容器实例化AndroidPhone 思路: 1.注册类型:把类型完整名称作为key添加到数据字典中,类型添加到数据字典的value中 2.获取实例:根据完整类型名称也就是key取出val ...
- Ioc 器管理的应用程序设计,前奏:容器属于哪里? 控制容器的反转和依赖注入模式
Ioc 器管理的应用程序设计,前奏:容器属于哪里? 我将讨论一些我认为应该应用于“容器管理”应用程序设计的原则. 模式1:服务字典 字典或关联数组是我们在软件工程中学到的第一个构造. 很容易看到使 ...
- ASP.NET Core Web 应用程序系列(一)- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)
在正式进入主题之前我们来看下几个概念: 一.依赖倒置 依赖倒置是编程五大原则之一,即: 1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象. 2.抽象不能依赖于具体,具体依赖于抽象. 其中上层就 ...
- 通过laravel理解IoC(控制反转)容器和DI(依赖注入)
原文地址: http://www.insp.top/learn-laravel-container ,转载务必保留来源,谢谢了! 容器,字面上理解就是装东西的东西.常见的变量.对象属性等都可以算是容器 ...
- PHP 在Swoole中使用双IoC容器实现无污染的依赖注入
简介: 容器(container)技术(可以理解为全局的工厂方法), 已经是现代项目的标配. 基于容器, 可以进一步实现控制反转, 依赖注入. Laravel 的巨大成功就是构建在它非常强大的IoC容 ...
- 从零写Java Web框架——实现Ioc依赖注入
大概思路 通过读取配置文件,获取框架要加载的包路径:base-package,类似于 Spring 配置文件中的: <context:component-scan base-package=&q ...
- 手写IOC容器
IOC(控制翻转)是程序设计的一种思想,其本质就是上端对象不能直接依赖于下端对象,要是依赖的话就要通过抽象来依赖.这是什么意思呢?意思就是上端对象如BLL层中,需要调用下端对象的DAL层时不能直接调用 ...
- [IoC容器Unity]第三回:依赖注入
1.引言 上节介绍了,Unity的Lifetime Managers生命周期,Unity具体实现依赖注入包含构造函数注入.属性注入.方法注入,所谓注入相当赋值,下面一个一个来介绍. 2.构造函数注入 ...
随机推荐
- [Redis-Python]发布订阅通过Redis异步发送邮件
接收订阅 #!/usr/bin/env pyhton # coding:utf-8 # @Time : 2020-02-16 21:36 # @Author : LeoShi # @Site : # ...
- React中ref的使用
直接获取DOM元素时使用的,一般情况下尽量不要使用ref
- 物理机安装ESXI6.7提示No Network Adapters的解决方案
下载好ESXI6.7.iso镜像,写入U盘后,提示No Network Adapters,找不到网卡驱动. 解决办法:需要重新封装ESXI,将对应的网卡驱动嵌入进来. 1.先下载VMware-Powe ...
- 智和网管平台SugarNMS网络综合监控等级保护安全解决方案
IT运维是一个很大的范畴,涉及到的部门.架构.技术.产品十分广泛.北京智和信通以等保标准为依据,依托丰富的网络安全行业经验,配套自主研发的智和网管平台SugarNMS,提升用户网络关键基础设施综合管理 ...
- 智和网管平台SugarNMS赋能AI智能化运维
11月14日,由<网络安全和信息化>和IT运维网联合主办的2019(第十届) IT运维大会上海站在锦荣国际大酒店如期召开.运维领域权威专家.技术领袖.各类运维相关技术产品提供商及服务商共同 ...
- RX.js6变化
RX.js变化 RxJS 6主要用于Angular应用程序,从Angular 6开始,它是一个强制依赖. 与RxJS版本5相比,RxJS 6(或更高版本)引入了两个重要更改: 1. import的导入 ...
- Ream--(objc)写事务精简方案
Ream--(objc)写事务精简方案 地址: REALM-- Realm官方提供的的写事务有两种方式: A[realm beginWriteTransaction]; // ... [realm c ...
- git命令小汇总和github
Git 简介 是什么 Git 也是一个版本控制管理软件 有什么用,可以解决什么问题 保存历史记录 多人协作 有了 SVN,为啥要学 Git Git 火 Git 相对于 SVN 来说,更强大,用户也非常 ...
- 如何在 vue 中添加权限控制管理?---vue中文社区
前言 在一个项目中,一些功能会涉及到重要的数据管理,为了确保数据的安全,我们会在项目中加入权限来限制每个用户的操作.作为前端,我们要做的是配合后端给到的权限数据,做页面上的各种各样的限制. 需求 因为 ...
- hadoop学习摘要
参考链接:https://www.zhihu.com/question/333417513 https://www.oschina.net/p/hbase hadoop环境搭建:https://blo ...