zoukankan      html  css  js  c++  java
  • 动手造轮子:实现一个简单的依赖注入(三) --- 支持属性注入

    动手造轮子:实现一个简单的依赖注入(三) --- 支持属性注入

    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

  • 相关阅读:
    怎样确定需求
    xampp进程和非进程执行
    将博客搬至CSDN
    管理心得
    数据库性能优化
    开发、架构总结
    activeMQ总结
    php数组操作函数
    Examples_08_08
    保险采购单的修复
  • 原文地址:https://www.cnblogs.com/weihanli/p/implement-dependency-injection-03.html
Copyright © 2011-2022 走看看