• .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设计原则的理解,希望大家也能有所提高。

    如有错误,欢迎指正,互相学习。谢谢!
  • 相关阅读:
    PHP xml_get_current_column_number() 函数
    PHP xml_get_current_byte_index() 函数
    PHP xml_error_string() 函数
    PHP utf8_encode() 函数
    PHP utf8_decode() 函数
    MySQL 资料库概论与MySQL 安装
    SEO之网站关键词的优化 :首页,内页关键字,长尾关键字
    前端开发chrome console的使用 :评估表达式 – Break易站
    chrome console的使用 : 异常和错误的处理 – Break易站
    SEO的基本概念 和 提交SITEMAP到搜索引擎
  • 原文地址:https://www.cnblogs.com/Ivan-Wu/p/15130564.html
Copyright © 2020-2023  润新知