zoukankan      html  css  js  c++  java
  • [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(1)

    前面俩种实现中,很多内部细节都无法知道,微软的框架也是为了屏蔽具体实现,只让我们关注接口。但是人都是充满好奇的,依赖注入到底是怎么实现的呢?

    微软又有怎样的实现呢?下面就为大家一一呈现(说实话,代码真不好读)

    先看下核心类:ServiceTable

     internal class ServiceTable
        {
            private readonly object _sync = new object();
    
            private readonly Dictionary<Type, ServiceEntry> _services;
            private readonly Dictionary<Type, List<IGenericService>> _genericServices;
            private readonly ConcurrentDictionary<Type, Func<ServiceProvider, object>> _realizedServices = new ConcurrentDictionary<Type, Func<ServiceProvider, object>>();
    
            public ServiceTable(IEnumerable<ServiceDescriptor> descriptors)
            {
                _services = new Dictionary<Type, ServiceEntry>();
                _genericServices = new Dictionary<Type, List<IGenericService>>();
    
                foreach (var descriptor in descriptors)
                {
                    var serviceTypeInfo = descriptor.ServiceType.GetTypeInfo();
                    if (serviceTypeInfo.IsGenericTypeDefinition)
                    {
                        Add(descriptor.ServiceType, new GenericService(descriptor));
                    }
                    else if (descriptor.ImplementationInstance != null)
                    {
                        Add(descriptor.ServiceType, new InstanceService(descriptor));
                    }
                    else if (descriptor.ImplementationFactory != null)
                    {
                        Add(descriptor.ServiceType, new FactoryService(descriptor));
                    }
                    else
                    {
                        Add(descriptor.ServiceType, new Service(descriptor));
                    }
                }
            }
    
            public ConcurrentDictionary<Type, Func<ServiceProvider, object>> RealizedServices
            {
                get { return _realizedServices; }
            }
    
            public bool TryGetEntry(Type serviceType, out ServiceEntry entry)
            {
                lock (_sync)
                {
                    if (_services.TryGetValue(serviceType, out entry))
                    {
                        return true;
                    }
                    else if (serviceType.GetTypeInfo().IsGenericType)
                    {
                        var openServiceType = serviceType.GetGenericTypeDefinition();
    
                        List<IGenericService> genericEntry;
                        if (_genericServices.TryGetValue(openServiceType, out genericEntry))
                        {
                            foreach (var genericService in genericEntry)
                            {
                                var closedService = genericService.GetService(serviceType);
                                if (closedService != null)
                                {
                                    Add(serviceType, closedService);
                                }
                            }
    
                            return _services.TryGetValue(serviceType, out entry);
                        }
                    }
                }
                return false;
            }
    
            public void Add(Type serviceType, IService service)
            {
                lock (_sync)
                {
                    ServiceEntry entry;
                    if (_services.TryGetValue(serviceType, out entry))
                    {
                        entry.Add(service);
                    }
                    else
                    {
                        _services[serviceType] = new ServiceEntry(service);
                    }
                }
            }
    
            public void Add(Type serviceType, IGenericService genericService)
            {
                lock (_sync)
                {
                    List<IGenericService> genericEntry;
                    if (!_genericServices.TryGetValue(serviceType, out genericEntry))
                    {
                        genericEntry = new List<IGenericService>();
                        _genericServices[serviceType] = genericEntry;
                    }
    
                    genericEntry.Add(genericService);
                }
            }
        }
    View Code

     首先看代码的属性:

    private readonly Dictionary<Type, ServiceEntry> _services;
    private readonly Dictionary<Type, List<IGenericService>> _genericServices;
    private readonly ConcurrentDictionary<Type, Func<ServiceProvider, object>> _realizedServices = new ConcurrentDictionary<Type, Func<ServiceProvider, object>>();

    ServiceEntry类等后面介绍,可以把它当作能够产生一个object对象的类。所以“_services”是存放类型和实例对应关系的字典。

    “_genericServices”顾名思义,肯定和泛型有关系,实际上“_genericServices”的Type是类似于“List<T>”这种包含泛型定义的类型。

    最后一个_realizedServices定义比较复杂。可能看不明白是什么意思。实际也是定义了一个字典表(ConcurrentDictionary),与Dictionary不同的是,对多线程支持较好。字典表的第一个泛型实参是Type,第二参数是一个Func代理;而这个Func代理(可以百度C#+Func查询详细的用法)的入参是ServiceProvider,返回值是object.

     [在注入获取实例时,会查询_realizedServices是否已经包含该实例,如果有则查询,如果没有则到_services中生产一个,之后将生成的结果加到realizedServices中,并且返回;但是如果_services也没有呢,则将_genericServices中泛型进行类型“实参话”,将所有类型匹配的都加入到_services中,之后从_services中获取]

    从类的构造函数中可以发现,根据ServiceDescriptor对象构建IService(IGenericService)顺序是:GenericService->InstanceService->FactoryService->Service(和Autofac、Ninject是不同的)。

    接口定义:IGenericService、IService、IServiceCallSite

    internal interface IGenericService
        {
            ServiceLifetime Lifetime { get; }
            IService GetService(Type closedServiceType);
        }
    internal interface IService
        {
            IService Next { get; set; }
            ServiceLifetime Lifetime { get; }
            IServiceCallSite CreateCallSite(ServiceProvider provider, ISet<Type> callSiteChain);
        }
    internal interface IServiceCallSite
        {
            object Invoke(ServiceProvider provider);
            Expression Build(Expression provider);
        }

    IServiceCallSite接口:类似一个工厂类,能够通过Invoke调用生成object对象,也就是依赖注入最后产生的对象都是由该接口的实例负责。

    IService接口:Lifetime生命周期,CreateCallSite通过ServiceProvider创建IServiceCallSite,也就是能够间接创建实例对象。我觉得Next属性放到接口里不算太恰当,Next对象引用自己,使得IService具有链性结构。

    IGenericService接口:产生一个IService接口。

    [此处有一个可以思考的问题,IGenericService和IService设计成俩个接口是容易理解的,泛型和非泛型差距很大,可以不共用一个接口。但是IService接口和IServiceCallSite接口为什么不可以合并成一个接口?接口定义如下所示:

     internal interface IService
        {
            ServiceLifetime Lifetime { get; }
            object Invoke(ServiceProvider provider);
        }

    ]

    ServiceEntry类

    internal class ServiceEntry
        {
            private object _sync = new object();
    
            public ServiceEntry(IService service)
            {
                First = service;
                Last = service;
            }
    
            public IService First { get; private set; }
            public IService Last { get; private set; }
    
            public void Add(IService service)
            {
                lock (_sync)
                {
                    Last.Next = service;
                    Last = service;
                }
            }
        }
    ServiceEntry

    ServiceEntry类相对比较简单。相当于一个IService的单向链表,之后包含了链表的起始节点,以及结束节点。Add方法能够让新节点添加到链表的尾部。
    [百思不得其解,为啥不使用LinkList这种列表结构,或者自己写个泛型类的列表,在IService内添加自引用,总觉得不是一种良好的设计]

    回头我们看下ServiceTableDictionary<Type, ServiceEntry> _services属性,实际上是对某个类型,注册了很多个IService接口,并且这些接口是按照列表顺序存放的。

    回头看看ServiceTable

    俩个Add方法很简单,判断该Type类型的列表/数组是否存在,如果存在,调用列表/数组的添加方法,不存在则创建一个。

    比较有意思的是TryGet方法,先在非泛型下搜索,如果不存在,则到泛型下搜索。并且将泛型“实参化”。这段代码值得我们深入研究。

     public bool TryGetEntry(Type serviceType, out ServiceEntry entry)
            {
                lock (_sync)
                {
                    if (_services.TryGetValue(serviceType, out entry))
                    {
                        return true;
                    }
                    else if (serviceType.GetTypeInfo().IsGenericType)
                    {
                        var openServiceType = serviceType.GetGenericTypeDefinition();
    
                        List<IGenericService> genericEntry;
                        if (_genericServices.TryGetValue(openServiceType, out genericEntry))
                        {
                            foreach (var genericService in genericEntry)
                            {
                                var closedService = genericService.GetService(serviceType);
                                if (closedService != null)
                                {
                                    Add(serviceType, closedService);
                                }
                            }
    
                            return _services.TryGetValue(serviceType, out entry);
                        }
                    }
                }
                return false;
            }
    TryGetEntry

    [ServiceTable的俩个属性Dictionary<Type, ServiceEntry> _services和Dictionary<Type, List<IGenericService>> _genericServices这俩个属性中一个使用单向列表,一个使用list,有洁癖的朋友会感觉很不爽有没有,有没有。为啥不能统一了让我们舒舒服服的呢]

  • 相关阅读:
    redis 事务 lq
    redis集群架构高可用分析 lq
    redis分布式锁 lq
    jvm垃圾回收 lq
    【攻防世界】逆向666
    第六届上海市大学生网络安全大赛wp
    【攻防世界】逆向answer_to_everying
    2021 DJBCTF(大吉大利杯) wp
    渗透靶机bossplayersCTF
    2020首届祥云杯部分wp
  • 原文地址:https://www.cnblogs.com/watermoon2/p/DependencyInjection.html
Copyright © 2011-2022 走看看