设为首页 加入收藏

TOP

手写实现简单版IOC(一)
2019-09-17 18:35:17 】 浏览:72
Tags:手写 实现 简单 IOC

概述

IOC (Inversion of Control) 控制反转,大家应该都比较熟悉了、应该也都有用过,这里就不具体介绍了。自己平时也有用到过IOC,但是对它的具体实现原理只有一个模糊的概念,所以决定自己手动实现一个简单IOC。

开始

首先呢我们得知道IOC的主要作用是什么,才能开始动手写。IOC主要不就是负责创建对象以及管理生命周期嘛,那我们就开始动手啦。

比如现在有一个IAnimal接口Animal继承接口,然后就是个Call的方法。一般我们使用的时候都是IAnimal animal=new Animal(); 如果是使用第三方IOC容器实现的话,我们需要先注册一下类型才能获取到实例。

所以我们先来个最简单的仿照这个过程:

新建一个Container,然后里面有一个类型注册的方法ResgisterType和一个返回实例的方法Rerolve,还有一个存储类型的字典,具体代码如下

        private static Dictionary<string, object> ContainerTypeDictionary = new Dictionary<string, object>();/// <summary>
        /// 注册类型
        /// </summary>
        /// <typeparam name="IT"></typeparam>
        /// <typeparam name="T"></typeparam>
        public void ResgisterType<IT,T>()
        {
            if (!ContainerTypeDictionary.ContainsKey(typeof(IT).FullName))
                ContainerTypeDictionary.Add(typeof(IT).FullName, typeof(T));
        }

        /// <summary>
        /// 根据注册信息生成实例
        /// </summary>
        /// <typeparam name="IT"></typeparam>
        /// <returns></returns>
        public IT Rerolve<IT>()
        {
            string key = typeof(IT).FullName;
            Type type = (Type)ContainerTypeDictionary[key];
       return (IT)Activator.CreateInstance(type);
     }

然后我们新建一个控制台测试一下

Container container = new Container();
container.ResgisterType<IAnimal, Animal>();
IAnimal animal= container.Rerolve<IAnimal>();

然后可以在不依赖具体对象Animal的情况下成功的创建一个animal实例。

 

之后我们就可以考虑复杂一点的情况了,现在我们的Animal类里没有做任何事,假如它的构造函数里依赖于另一个对象呢,这样我们的程序肯定是会报错的。比如下面这样:

public class Animal: IAnimal
    {
        public Animal(Dog dog)
        {
            
        }
    }

 

我们容器目前能创建的对象实例,只有通过ResgisterType方法注册过类型的,而像Animal里依赖的不能实现创建,所以这个时候就需要用到依赖注入了。

关于依赖注入与控制反转的关系,我个人的理解是:控制反转是一种设计思想,而依赖注入则是实现控制反转思想的方法。

IOC容器一般依赖注入有三种:构造函数注入、方法注入、属性注入。

那么我们就来照瓢画葫芦,实现一下构造函数注入。一般IOC容器构造函数注入是通过一个特性来识别注入的,如果没有标记特性则去找构造函数参数个数最多的,我们就按照这个思路来。

首先我们新建一个LInjectionConstructorAttribute类,只需继承Attribute就行了。

 

public class LInjectionConstructorAttribute :Attribute
    {
    }

 

然后在刚才那个Animal构造函数上标记上特性,接下来就开始写代码。

/// <summary>
        /// 根据注册信息生成实例
        /// </summary>
        /// <typeparam name="IT"></typeparam>
        /// <returns></returns>
        public IT Rerolve<IT>()
        {
            string key = typeof(IT).FullName;
            Type type = (Type)ContainerTypeDictionary[key];

            return (IT)CreateType(type);
        }
/// <summary>
        /// 根据提供的类型创建类型实例并返回
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private object CreateType(Type type)
        {
            var ctorArray = type.GetConstructors();
            if (ctorArray.Count(c => c.IsDefined(typeof(LInjectionConstructorAttribute), true)) > 0)
            {
                //获取带特性标记的构造函数参数
                foreach (var cotr in type.GetConstructors().Where(c => c.IsDefined(typeof(LInjectionConstructorAttribute), true)))
                {
                    var paraArray = cotr.GetParameters();//获取参数数组
                    if (paraArray.Length == 0)
                    {
                        return Activator.CreateInstance(type);
                    }

                    List<object> listPara = new List<object>();
                    foreach (var para in paraArray)
                    {
                        string paraKey = para.ParameterType.FullName;//参数类型名称
                                                                     //从字典中取出缓存的目标对象并创建对象
                        Type paraTargetType = (Type)ContainerTypeDictionary[para
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇两篇文章带你走入.NET Core 世界.. 下一篇【vue】项目编译报错 Error: No P..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目