动手造轮子:实现一个简单的依赖注入(三) --- 支持属性注入
Intro
前面写了几篇依赖注入的文章,有兴趣的小伙伴可以参考文末 Reference
部分中的链接,一直有小伙伴希望增加属性注入的支持,昨天试着加了一下,思路很简单,在获取到服务实例之后检查实例中有没有需要注入的属性,如果有并且不为 null
就从服务容器中获取一个对应属性类型的实例
代码修改
FromServiceAttribute
完整的代码修改可以参考这个 commit https://github.com/WeihanLi/WeihanLi.Common/commit/91dc0b515d12e7c036771fba9419824cd0219544
首先我们需要增加一个 FromServiceAttribute
用来标识哪些属性需要注入,代码如下:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]public sealed class FromServiceAttribute : Attribute{}
这里 AttributeTargets
除了属性之外增加了字段和参数,是想可能以后会用到,参数典型的应用场景就是类似于 asp.net core 里的 [FromServices]
用来实现方法注入参数
EnrichObject
增加了一个 EnrichObject
方法,用来在获取到服务实例之后,对服务实例做一些补充的配置,如我们要加的属性注入,如果我们要加字段注入等也可以在这个方法内完成,来看实现:
private object EnrichObject(object obj){ if (null != obj) { // PropertyInjection var type = obj.GetType(); foreach (var property in CacheUtil.TypePropertyCache.GetOrAdd(type, t => t.GetProperties()) .Where(x => x.IsDefined(typeof(FromServiceAttribute)))) { if (property.GetValueGetter()?.Invoke(obj) == null) { property.GetValueSetter()?.Invoke( obj, GetService(property.PropertyType) ); } } } return obj;}
上面的逻辑就是获取这个 object 定义的所有需要注入的属性,如果属性的值不为 null 则,从服务容器中获取对应的服务实例,之所以要检查是不是null
上面的 CacheUtil.TypePropertyCache
是一个 Type 为 key,PropertyInfo 数组为 Value 的并发字典,用来缓存类型的属性
GetValueGetter/GetValueSetter 是 PropertyInfo 的扩展方法,利用表达式树和缓存提高属性 Get/Set 的效率
GetSertviceInstance
修改原来的 GetServiceInstance 方法为 GetServiceInstanceInternal,增加一个一样的方法,实现逻辑是在 GetServiceInstanceInternal 的基础上调用上面的 Enrich 方法来实现属性注入
More
虽然增加了属性注入的支持,但是还是不太推荐使用,从上面属性注入的代码中可以看得到,如果用不好很容易出现循环依赖的问题,而且用构造器注入的话依赖关系很清晰,分析方法的构造方法即可,如果要使用属性注入请谨慎使用
Reference
https://github.com/WeihanLi/WeihanLi.Common/commit/91dc0b515d12e7c036771fba9419824cd0219544
https://github.com/WeihanLi/WeihanLi.Common/tree/dev/src/WeihanLi.Common/DependencyInjection
https://www.cnblogs.com/weihanli/p/implement-dependency-injection.html
https://www.cnblogs.com/weihanli/p/implement-dependency-injection-01.html
https://www.cnblogs.com/weihanli/p/implement-dependency-injection-02.html