zoukankan      html  css  js  c++  java
  • .Net 手写简易依赖注入容器

        相信大部分人都用过.Net依赖注入容器,但可能只会使用不了解其原理,之前通过Rider这个IDE了解过.net core 依赖注入容器大致原理。

    打算自己去实现一个简单的容器加深理解。

        


      依赖注入对象有三种生命周期:

      1、Transient

      2、Scope

      3、Singeton

     要如何实现这三种方式呢

    一开始我们要注册对象并指定生命周期,那么如何保存这些注入的对象类型呢,用根据不同生命周期去保存:

     private static Dictionary<string, (LifeTime, Type)> types = new Dictionary<string, (LifeTime, Type)>();
     private static Dictionary<string, object> SingletonObjs = new Dictionary<string, object>();

    这里的LifeTime就是定义生命周期的枚举:

      public enum LifeTime
        {
            Transient,
    
            Scope,
    
            Singleton
        }

    然后singletonObjs是单例模式下保存的对象,当有用到的时候从里面取出对象即可,那么注册对象就是向types 字典放入对象,很简单就可以理解:

            /// <summary>
            /// transient
            /// </summary>
            /// <typeparam name="TFrom"></typeparam>
            /// <typeparam name="TTo"></typeparam>
            public static void RegisterTransientType<TFrom, TTo>() where TTo : TFrom
            {
                types.Add(typeof(TFrom).FullName, (LifeTime.Transient, typeof(TTo)));
            }
    
            /// <summary>
            /// Scope
            /// </summary>
            /// <typeparam name="TFrom"></typeparam>
            /// <typeparam name="TTo"></typeparam>
            public static void RegisterScopeType<TFrom, TTo>() where TTo : TFrom
            {
                types.Add(typeof(TFrom).FullName, (LifeTime.Transient, typeof(TTo)));
            }
        
    
            /// <summary>
            /// Singleton
            /// </summary>
            /// <typeparam name="TFrom"></typeparam>
            /// <typeparam name="TTo"></typeparam>
            public static void RegisterSingletonType<TFrom, TTo>() where TTo : TFrom
            {
                types.Add(typeof(TFrom).FullName, (LifeTime.Singleton, typeof(TTo)));
                Type type = typeof(TTo);
                var obj = Resolve<TFrom>(type);
                SingletonObjs.Add(typeof(TFrom).FullName, obj);
            }    

     注册完对象就可以使用了,下面是获取对象的方法。当然这里只是举一个简单的例子,.Net依赖注入容器是非常强大的,不能混为一谈。

            public static T Resolve<T>()
            {
                if (!types.ContainsKey(typeof(T).FullName))
                    return default;
                var obj = types[typeof(T).FullName];
                Type type = obj.Item2;
                if (obj.Item1 == LifeTime.Singleton)
                {
                    if (SingletonObjs.ContainsKey(typeof(T).FullName))
                    {
                        var result = SingletonObjs[typeof(T).FullName];
                        if (result is T)
                        {
                            return (T)result;
                        }
                    }
                    else
                    {
                        return default;
                    }
                }
    
                return Resolve<T>(type);
            }
    
            public static T Resolve<T>(Type type)
            {
                //首先获取构造函数的type
                var constructorInfos = type.GetConstructors();
                List<object> list = new List<object>();
                foreach (var ctor in constructorInfos)
                {
                    foreach (var item in ctor.GetParameters())
                    {
                        var itemType = item.ParameterType;
                        var itemTargeType = types[itemType.FullName].Item2;
                        var target = Resolve<object>(itemTargeType);
                        list.Add(target);
                    }
                }
                T t = default(T);
                t = (T)Activator.CreateInstance(type, list.ToArray());
    
                return t;
            }

    通过Resolve达到注册的目的,例子演示:

    先注册:           
    RegisterSingletonType<ISortService, SortService>(); 然后获取: private readonly ISortService sortService; public TestController() { sortService = DependencyInjectionContainer.Resolve<ISortService>(); }

    这里要说明一下,这里和.Net 依赖注入还是有所区别的,这里没有构造注入,而且.Net的scope是和请求的Context绑定以达到scope注入的目的的。

    通过实现简易IOC,更加加深了IOC设计原则的理解,希望大家也能有所提高。

    如有错误,欢迎指正,互相学习。谢谢!
  • 相关阅读:
    ORACLE各种对象、概念及关系整理(一文读懂)
    Spring面试题总结及答案
    MySQL面试总结
    可变参数,你还为方法的参数而烦恼吗?可变参数,让你的头发从此“茂密”!
    java编译报错: 找不到或无法加载主类 Demo.class 的解决方法
    java编译报错 错误: 编码GBK的不可映射字符
    sql server2017开启远程连接
    sql server一些快捷方式和操作技巧
    sql server无法连接本地服务器
    phpStorm+xdebug调试(php7.3)
  • 原文地址:https://www.cnblogs.com/Ivan-Wu/p/15130564.html
Copyright © 2011-2022 走看看