.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设计原则的理解,希望大家也能有所提高。
如有错误,欢迎指正,互相学习。谢谢!