.net 手动实现简易IOC容器

现在的编程思想,离不开IOC依赖注入,手写实现一个简易IOC容器,更深入理解依赖注入
还没了解IOC的可以查阅.net IOC框架 Unity&Autofac

本文章主要实现

  • IOC容器基础注册
  • 进阶完善别名以及构造函数注入
  • 对象的生命周期管理

一、IoC容器实现

测试接口类

    public interface ILanguage
    {
        public string GetContent();
    }

测试接口实现类

    public class Chinese : ILanguage
    {
        public string GetContent()
        {
            return "学习中文";
        }
    }

    public class English : ILanguage
    {
        public string GetContent()
        {
            return "Learning English";
        }
    }

自定义容器接口类

public interface IMyContainer
    {
        /// 
        /// 注册单一类型
        /// 
        /// 
        void RegisterType();

        /// 
        /// 注册单一类型
        /// 
        /// 
        /// 别名
        void RegisterType(string name);

        /// 
        /// 映射关系
        /// 
        /// 
        /// 
        void RegisterType();
        /// 
        /// 映射关系
        /// 
        /// 
        /// 
        /// 别名
        void RegisterType(string name);

        /// 
        /// 解析类型
        /// 
        /// 
        /// 
        TType Resolve();

        /// 
        /// 解析类型
        /// 
        /// 
        /// 别名
        /// 
        TType Resolve(string name);

容器接口实现类

    public class MyContainer : IMyContainer
    {
         //键用来映射关系,使用字典作为登记本
        private static readonly Dictionary ContainerDictionary = new Dictionary();
        public void RegisterType()
            => RegisterType(null);
        public void RegisterType()
            => RegisterType(null);

        public void RegisterType(string name)=>
            RegisterType(null);

        public void RegisterType(string name)
        {
            string key = typeof(TType).FullName;
            if (!string.IsNullOrEmpty(name)) key = name;
            if (ContainerDictionary.ContainsKey(key))
                ContainerDictionary[key] = typeof(TImplementation); //如果存在采取覆盖形式
            else
                ContainerDictionary.Add(key, typeof(TImplementation));//将传进来的泛型Type进行关系映射
        }

        public TType Resolve() =>
            Resolve(null);

        public TType Resolve(string name)
        {
            //解析泛型Type获取key
            var key = typeof(TType).FullName;
            if (!string.IsNullOrEmpty(name)) key = name;
            // 根据key从容器中获取实现类
            var type = (Type)ContainerDictionary[key];

            //创建对象
            return (TType)Activator.CreateInstance(type);
        }
    }

main函数依赖注入测试

    static void Main(string[] args)
    {
        var container = new MyContainer();
        container.RegisterType();
        //使用别名注册
        container.RegisterType("english"); 
        var language = container.Resolve();
        var english = container.Resolve("english");
        Console.WriteLine(language.GetContent());
        Console.WriteLine(english.GetContent());
        Console.Read();
    }

输出结果

image.png

二、构造函数注入

创建特性类标记构造函数

    public class MyinjectionAttribute : Attribute
    {
    }

使用自定义创建实例类进行对象实例化
1.优先使用被特性标记的构造函数
2.没有特性标记选择参数最多的构造函数,参数个数一致,按默认顺序选择第一个

        //多个构造函数选择构造函数来创建实例
        //1.优先使用被特性标记的构造函数
        //2.没有特性标记选择参数最多的构造函数,参数个数一致,按默认顺序选择第一个

        /// 
        /// 创建实例
        /// 
        /// 
        /// 
        private object CreateInstance(Type type)
        {
            //获取所有的构造函数
            var ctors = type.GetConstructors();

            //获取被标记的构造函数
            var ctor = ctors.FirstOrDefault(t => t.IsDefined(typeof(MyinjectionAttribute), true));
            if (ctor != null) CreateInstance(type, ctor);

            //没有特性获取参数最多的一个
            ctor = ctors.OrderByDescending(t => t.GetParameters().Length).First();

            return CreateInstance(type, ctor);
        }

        /// 
        /// 构造函数注入
        /// 
        /// 
        /// 
        /// 
        private object CreateInstance(Type type, ConstructorInfo ctor)
        {
            //获取构造函数参数
            var paraArray = ctor.GetParameters();
            if (paraArray.Length == 0)
            {
                return Activator.CreateInstance(type);
            }

            var parameters = new List();
            foreach (var para in paraArray)
            {
                //通过反射获取参数类型名
                var paraKey = para.ParameterType.FullName;
                //根据paraKey从字典获取已注册的实现类
                var paraType = (Type)ContainerDictionary[paraKey];

                // 递归注入构造参数
                var paraObj = CreateInstance(paraType);
                //将对象存储在list数组
                parameters.Add(paraObj);
            }

            return Activator.CreateInstance(type, parameters.ToArray());
        }
 
 

修改Resolve函数调用自身创建对象函数CreateInstance

        public TType Resolve(string name)
        {
            //解析泛型Type获取key
            var key = typeof(TType).FullName;
            if (!string.IsNullOrEmpty(name)) key = name;
            // 根据key从容器中获取实现类
            var type = (Type)ContainerDictionary[key];

            //创建对象
            return (TType)CreateInstance(type);
        }

新建Learn类进行测试

    public class Learn
    {
        private ILanguage Language { get; set; }
         
        //标记特性
        [Myinjection]
        public Learn(ILanguage language)
        {
            Language = language;
        }

        public void Read()
        {
            Console.WriteLine(Language.GetContent());
        }
    }

main函数

        static void Main(string[] args)
        {
            var container = new MyContainer();
            container.RegisterType();
            //注入learn
            container.RegisterType();

            var learn = container.Resolve();
            learn.Read();
            Console.Read();
        }

测试结果:

image.png

三、生命周期管理

这里实现三种常用生命周期模式:单例,瞬时,线程单例(作用域)

定义生命周期管理接口类,便于扩展

    public interface ILifeTimeManager
    {
        object CreateInstance(Type type, params object[] args);
    }

单例模式实现类

    public class SingletonLifeTimeManager : ILifeTimeManager
    {
        //单例字典
        private readonly Dictionary _singletonDictionary = new Dictionary();
        public object CreateInstance(Type type, params object[] args)
        {
            var key = type.FullName;
            if (_singletonDictionary.ContainsKey(key)) return  _singletonDictionary[key];

            var instance = Activator.CreateInstance(type, args);
            _singletonDictionary.Add(key, instance);
            return instance;
        }
    }

瞬时模式实现类

    public class TransientLifeTimeManger : ILifeTimeManager
    {
        public object CreateInstance(Type type, params object[] args)
        {
            return Activator.CreateInstance(type, args);
        }
    }

线程单例实现类

    public class PerThreadLifeTimeManager : ILifeTimeManager
    {
        //通过线程本地存储进行线程单例管理
        private readonly ThreadLocal> _perThreadDictonary =
            new ThreadLocal>();
        public object CreateInstance(Type type, params object[] args)
        {
            //判断线程存储是否存在字段对象
            if (_perThreadDictonary.Value == null)
                _perThreadDictonary.Value = new Dictionary();

            var key = type.FullName;
            if (_perThreadDictonary.Value.ContainsKey(key)) return _perThreadDictonary.Value[key];

            var instance = Activator.CreateInstance(type, args);
            _perThreadDictonary.Value.Add(key, instance);
            return instance;
        }
    }

定义生命周期类型静态类(用于管理生命周期类型)

    public static class TypeLifeTime
    {
        public static ILifeTimeManager Singleton = new SingletonLifeTimeManager();
        public static ILifeTimeManager Transient = new TransientLifeTimeManger();
        public static ILifeTimeManager PerThread = new PerThreadLifeTimeManager();
    }

定义保存注册映射信息实体类,以及扩展方法类

    public class RegisteredType
    {
        public Type TargetType { get; set; }

        public ILifeTimeManager LifeTimeManager { get; set; }
    }

    public static class RegisteredTypeExtension
    {
        public static object CreateInstance(this RegisteredType type, params object[] args)
        {
            //使用生命周期管理创建实例
            return type.LifeTimeManager.CreateInstance(type.TargetType, args);
        }
    }

IMyContainer 接口类新增生命周期管理接口

        /// 
        /// 注册单一类型
        /// 
        /// 
        /// 生命周期管理
        void RegisterType(ILifeTimeManager lifeTimeManager);

        /// 
        /// 注册单一类型
        /// 
        /// 
        /// 别名
        /// 生命周期管理
        void RegisterType(string name, ILifeTimeManager lifeTimeManager);

        /// 
        /// 映射关系
        /// 
        /// 
        /// 
        /// 生命周期管理
        void RegisterType(ILifeTimeManager lifeTimeManager);

        /// 
        /// 映射关系
        /// 
        /// 
        /// 
        /// 别名
        /// 生命周期管理
        void RegisterType(string name, ILifeTimeManager lifeTimeManager);

MyContainer 接口实现类修改如下

    public class MyContainer : IMyContainer
    {
        //键用来映射关系,使用字典作为登记本
        private static readonly Dictionary ContainerDictionary = new Dictionary();
        public void RegisterType()
            => RegisterType("");
        public void RegisterType()
            => RegisterType("");

        public void RegisterType(string name) =>
            RegisterType("");

        public void RegisterType(string name)=>
            RegisterType(name, TypeLifeTime.Transient);

        public void RegisterType(ILifeTimeManager lifeTimeManager)=>
             RegisterType(lifeTimeManager);

        public void RegisterType(ILifeTimeManager lifeTimeManager)=>
            RegisterType("", lifeTimeManager);

        public void RegisterType(string name, ILifeTimeManager lifeTimeManager) =>
            RegisterType(name, lifeTimeManager);

        public void RegisterType(string name, ILifeTimeManager lifeTimeManager)
        {
            string key = typeof(TType).FullName;
            if (!string.IsNullOrEmpty(name)) key = name;
            if (ContainerDictionary.ContainsKey(key)) //如果存在覆盖
                ContainerDictionary[key] = new RegisteredType
                {
                    TargetType = typeof(TImplementation),
                    LifeTimeManager = lifeTimeManager
                }; 
            else
                ContainerDictionary.Add(key, new RegisteredType
                {
                    TargetType = typeof(TImplementation),
                    LifeTimeManager = lifeTimeManager
                });//将传进来的泛型Type进行关系映射
        }

        public TType Resolve() =>
            Resolve("");

        public TType Resolve(string name)
        {
            //解析泛型Type获取key
            var key = typeof(TType).FullName;
            if (!string.IsNullOrEmpty(name)) key = name;
            // 根据key从容器中获取实现类
            var type = ContainerDictionary[key];

            //创建对象
            return (TType)CreateInstance(type);
        }

        //多个构造函数选择构造函数来创建实例
        //1.优先使用被特性标记的构造函数
        //2.没有特性标记选择参数最多的构造函数,参数个数一致,按默认顺序选择第一个

        /// 
        /// 创建实例
        /// 
        /// 
        /// 
        private object CreateInstance(RegisteredType type)
        {
            //获取所有的构造函数
            var ctors = type.TargetType.GetConstructors();

            //获取被标记的构造函数
            var ctor = ctors.FirstOrDefault(t => t.IsDefined(typeof(MyinjectionAttribute), true));
            if (ctor != null) CreateInstance(type, ctor);

            //没有特性获取参数最多的一个
            ctor = ctors.OrderByDescending(t => t.GetParameters().Length).First();

            return CreateInstance(type, ctor);
        }

        /// 
        /// 构造函数注入
        /// 
        /// 
        /// 
        /// 
        private object CreateInstance(RegisteredType type, ConstructorInfo ctor)
        {
            //获取构造函数参数
            var paraArray = ctor.GetParameters();
            if (paraArray.Length == 0)
            {
              return type.CreateInstance();
            }

            var parameters = new List();
            foreach (var para in paraArray)
            {
                //通过反射获取参数类型名
                var paraKey = para.ParameterType.FullName;
                //根据paraKey从字典获取已注册的实现类
                var paraType = ContainerDictionary[paraKey];

                // 递归注入构造参数
                var paraObj = CreateInstance(paraType);
                //将对象存储在list数组
                parameters.Add(paraObj);
            }

            //调用生命周期管理器创建时间方法
            //type.LifeTimeManager.CreateInstance(type, parameters.ToArray());

            //这里使用扩展类调用生命周期管理器创建时间方法
            return type.CreateInstance(parameters.ToArray());
        }
    }
 
 

接下来测试一下
main函数

        static void Main(string[] args)
        {
            var container = new MyContainer();
            //依赖注入 瞬时默认
            container.RegisterType();
            var language1 = container.Resolve();
            var language2 = container.Resolve();
            Console.WriteLine($"-----------------------瞬时默认-------------------------");
            Console.WriteLine($"language1 与 language2:{ReferenceEquals(language1, language2)}\r\n");

            //线程单例
            Console.WriteLine($"-----------------------线程单例-------------------------");
            container.RegisterType(TypeLifeTime.PerThread);
            ILanguage tlanguage1 = null;
            var task1 = Task.Run(() => {
                tlanguage1 = container.Resolve();
                Console.WriteLine($"tlanguage1 线程id:{Thread.CurrentThread.ManagedThreadId}");
            });
            ILanguage tlanguage2 = null;
            ILanguage tlanguage3 = null;
            var task2 = Task.Run(() => {
                tlanguage2 = container.Resolve();
                tlanguage3 = container.Resolve();
                Console.WriteLine($"tlanguage2 线程id:{Thread.CurrentThread.ManagedThreadId}");
                Console.WriteLine($"tlanguage3 线程id:{Thread.CurrentThread.ManagedThreadId}");
            });

            task1.Wait();
            task2.Wait();
            Console.WriteLine($"tlanguage1 与 tlanguage2 :{ReferenceEquals(tlanguage1, tlanguage2)}");
            Console.WriteLine($"tlanguage2 与 tlanguage3 :{ReferenceEquals(tlanguage2, tlanguage3)}\r\n");

            //单例模式
            container.RegisterType(TypeLifeTime.Singleton);
            var slanguage1 = container.Resolve();
            var slanguage2 = container.Resolve();
            Console.WriteLine($"-----------------------单例模式-------------------------");
            Console.WriteLine($"slanguage1 与 slanguage2:{ReferenceEquals(slanguage1, slanguage2)}");

            Console.Read();
        }

输出结果:


image.png

附上项目结构图:


image.png

文章就到这里了,还有很多功能未实现(如函数注入,属性注入等),主要为了了解学习IOC容器- -
项目源码:https://github.com/booker1/IOC

你可能感兴趣的:(.net 手动实现简易IOC容器)