3、手写Unity容器--第N层依赖注入

这个场景跟《手写Unity容器--极致简陋版Unity容器》不同,这里构造AndroidPhone的时候,AndroidPhone依赖于1个IPad

1、IPhone接口

namespace SimplestUnity_nLayer
{
    interface IPhone
    {
        void Call();
    }
}

2、AndroidPhone实现

namespace SimplestUnity_nLayer
{
    public class AndroidPhone : IPhone
    {
        public AndroidPhone(IPad iPad, IHeadPhone iHeadPhone)
        {
            Console.WriteLine("{0}构造函数", this.GetType().Name);
        }
    }
}

3、IPad接口

namespace SimplestUnity_nLayer
{
    public interface IPad
    {
        void Show();
    }
}

4、IPad实现

namespace SimplestUnity_nLayer
{
    public class AndroidPad:IPad
    {
        public AndroidPad()
        {
            Console.WriteLine("{0}构造函数", this.GetType().Name);
        }

        public void Show()
        {
            Console.WriteLine("看{0}", this.GetType().Name);
        }
    }
}

5、IHeadPhone接口

namespace SimplestUnity_nLayer
{
    public interface IHeadPhone
    {

    }
}

6、IHeadPhone实现

namespace SimplestUnity_nLayer
{
    public class HeadPhone : IHeadPhone
    {
        public HeadPhone(IRootPhone iRootPhone)
        {
            Console.WriteLine("Headphone 被构造");
        }
    }
}

7、IRootPhone接口

namespace SimplestUnity_nLayer
{
    public interface IRootPhone
    {

    }
}

8、IRootPhone实现

namespace SimplestUnity_nLayer
{
    public class RootPhone : IRootPhone
    {
        public RootPhone()
        {
            Console.WriteLine("RootPhone 被构造");
        }
    }
}

9、容器--接口

public interface IDavidContainer
{
    void RegisterType<TFrom, TTo>();

    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)) > 0)
            {
                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>();
            //递归:隐形的跳出条件,条件就是GetParameters结果为空,targetType拥有无参数构造函数
            foreach (var para in currentCtor.GetParameters())
            {
                //得到的参数类型是IPad,抽象无法创建实例
                var paraType = para.ParameterType;
                //所以根据IPad Key,得到AndroidPad类型,具体类型就可以创建实例
                var targetParaType = containerDictionary[paraType.FullName];
                //继续检查targetParaType的构造函数,不能直接创建实例了
                Object obj = this.CreateInstance(targetParaType);

                paraList.Add(obj);
            }
            return Activator.CreateInstance(type, paraList.ToArray());
        }
    }
}

11、调用

class Program
{
    static void Main(string[] args)
    {
        DaivdContainer davidContainer = new DaivdContainer();
        davidContainer.RegisterType<IPhone, AndroidPhone>();
        davidContainer.RegisterType<IPad, AndroidPad>();
        davidContainer.RegisterType<IHeadPhone, HeadPhone>();
        davidContainer.RegisterType<IRootPhone, RootPhone>();
        IPhone iphone = davidContainer.Resolve<IPhone>();
        iphone.Call();
    }
}

原文地址:https://www.cnblogs.com/menglin2010/p/12109529.html

时间: 2024-10-10 16:18:02

3、手写Unity容器--第N层依赖注入的相关文章

ASP.NET Core Web 应用程序系列(一)- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入

在正式进入主题之前我们来看下几个概念: 一.依赖倒置 依赖倒置是编程五大原则之一,即: 1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象. 2.抽象不能依赖于具体,具体依赖于抽象. 其中上层就是指使用者,下层就是指被使用者. 二.IoC控制反转 控制反转(IoC,全称Inversion of Control)是一种思想,所谓“控制反转”,就是反转获得依赖对象的过程. 三.依赖注入(DI) 依赖注入设计模式是一种在类及其依赖对象之间实现控制反转(IoC)思想的技术. 所谓依赖注入(DI,全

[IoC容器Unity]第三回:依赖注入

上节介绍了,Unity的Lifetime Managers生命周期,Unity具体实现依赖注入包含构造函数注入.属性注入.方法注入,所谓注入相当赋值,下面一个一个来介绍. 2.构造函数注入 Unity利用Resolve方法解析一个对象,都是调用注册类型的构造函数来初始化的,初始化时,Unity能够控制初始化的值,当然,我们要给Unity提供足够的原料,要不然也是巧妇难无米之炊,下面看一些简单的示例. 先准备几个类如下: /// <summary> /// 班级接口 /// </summa

控制容器的反转和依赖注入模式

本文依旧是一篇译文,写于作者在开发.net core 半年后的进阶学习时刻! 这篇文章很长,一口气看完得花二十分钟,大家要做好心理准备! 摘要:Java社群近来掀起了一阵轻量级容器的热潮,这些容器能够帮助开发者将来自不同项目的组件组装成为一个内聚的应用程序.在它们的背后有着同一个模式,这个模式决定了这些容器进行组件装配的方式.人们用一个大而化之的名字来称呼这个模式:”控制反转”(Inversion ofControl,IoC).在本文中,我将深入探索这个模式的工作原理,给它一个更能描述其特点的名

spring源码解析之IOC容器(三)——依赖注入

上一篇主要是跟踪了IOC容器对bean标签进行解析之后存入Map中的过程,这些bean只是以BeanDefinition为载体单纯的存储起来了,并没有转换成一个个的对象,今天继续进行跟踪,看一看IOC容器是怎样实例化对象的. 我们都使用过以下代码: 1 FileSystemXmlApplicationContext context=new FileSystemXmlApplicationContext("bean.xml"); 2 User user=context.getBean(&

从零写Java Web框架——实现Ioc依赖注入

大概思路 通过读取配置文件,获取框架要加载的包路径:base-package,类似于 Spring 配置文件中的: <context:component-scan base-package="*"/> 将 base-package 路径下的所有类都加载,并保存在一个 Set<Class<?>> classSet 中: 初始化 Bean 容器,遍历 classSet,通过反射获得 Class 的实例,并保存 Class 与 Class实例的映射关系,即

【ASP.Net MVC3 】使用Unity 实现依赖注入

什么是Unity? Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入.Unity可以处理那些从事基于组件的软件工程的开发人员所面对的问题.构建一个成功应用程序的关键是实现非常松散的耦合设计.松散耦合的应用程序更灵活,更易于维护.这样的程序也更容易在开发期间进行测试.你可以模拟对象,具有较强的具体依赖关系的垫片(轻量级模拟实现),如数据库连接,网络连接,ERP连接,和丰富的用户界面组件.例如,处理客户信息的对象可能依赖于其他对象访问的数据存储,验证信息,并检查该用户是

Unity 之依赖注入

什么是Unity? Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入.Unity可以处理那些从事基于组件的软件工程的开发人员所面对的问题.构建一个成功应用程序的关键是实现非常松散的耦合设计.松散耦合的应用程序更灵活,更易于维护.这样的程序也更容易在开发期间进行测试.你可以模拟对象,具有较强的具体依赖关系的垫片(轻量级模拟实现),如数据库连接,网络连接,ERP连接,和丰富的用户界面组件.例如,处理客户信息的对象可能依赖于其他对象访问的数据存储,验证信息,并检查该用户是

用Decorator实现依赖注入,像Java一样写后台

最近闲来无事,突发奇想,也顺便练练手,于是就萌生了,能否用typescript的decorator写一个Nodejs SpringMVC,通过依赖注入,自动实现文件加载,实例化等.然后就有了这个项目. 该项目支持: 依赖注入Controller ,Service 注入GET/POST/PUT/DELETE/PATCH等rest方法 解析rest api的参数,例如RequestParam 上传文件支持Multer 支持在vscode里面直接debug typescript 的代码 想学习如何de

如何编写一个简单的依赖注入容器

随着大规模的项目越来越多,许多项目都引入了依赖注入框架,其中最流行的有Castle Windsor, Autofac和Unity Container. 微软在最新版的Asp.Net Core中自带了依赖注入的功能,有兴趣可以查看这里. 关于什么是依赖注入容器网上已经有很多的文章介绍,这里我将重点讲述如何实现一个自己的容器,可以帮助你理解依赖注入的原理. 容器的构想 在编写容器之前,应该先想好这个容器如何使用. 容器允许注册服务和实现类型,允许从服务类型得出服务的实例,它的使用代码应该像 var