前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Core官方DI解析(2)-ServiceProvider

Core官方DI解析(2)-ServiceProvider

原创
作者头像
莫问今朝
发布2018-11-27 08:44:28
6350
发布2018-11-27 08:44:28
举报
文章被收录于专栏:博客园

/ServiceProvide

ServiceProvider是我们用来获取服务实例对象的类型,它也是一个特别简单的类型,因为这个类型本身并没有做什么,其实以一种代理模式,其核心功能全部都在IServiceProviderEngine实现类中

ServiceProvider还具有一个扩展类型ServiceProviderServiceExtensions,在扩展类型之中实现了一些我们经常使用的获取服务实例方法,比如GetServices()GetRequiredService()方法,还实现了获取子容器方法CreateScope(),下面来具体的看一下这个类型

从下面代码看到ServiceProvider一个实现了三个接口

IServiceProvider 获取服务接口,这个接口是位于System程序集下的,而这个接口只有一个object GetService(Type serviceType)方法,也就是说我们常用很多方法包括泛型获取都是来自于扩展类中

IDisposable 说明此对象需要被释放

IServiceProviderEngineCallback 这个接口就是检验validateScopes时使用的,接口具有两个方法**OnCreate()**和**OnResolve()**分别用于创建服务实例时缓存和校验,

代码语言:txt
复制
public sealed class ServiceProvider : IServiceProvider, IDisposable, IServiceProviderEngineCallback

{}
代码语言:txt
复制
`ServiceProvider`这个类型其实挺简单,从下面代码中\*\*GetService()\*\*方法可以看出它只是代理了一个`IServiceProviderEngine`实现类型,

**_engine**: 作为一个IServiceProviderEngine接口,这个接口是ServiceProvider的工作引擎接口,也是一个核心类型,下一章再详细讲解这个接口及其实现类型

**_callSiteValidator**: 这是一个验证**ValidateScopes**的缓存类型(访问者模式),可以看到,在构造函数中只有当**ValidateScopes**为true时才实例化此对象,然后在获取服务实例时通过**OnCreate()**进行缓存和通过**OnResolve()**进行校验

代码语言:txt
复制
`ServiceProvider`的实例化方式在上一章已经说过,利用`ServiceDescriptor`集合和`ServiceProviderOptions`进行实例化,可以看到,在构造方法中首先通过\*\*ValidateScopes\*\*属性来进行实例化`CallSiteValidator`和将当前对象赋值给`IServiceProviderEngineCallback`类型变量

将**this**赋值给**IServiceProviderEngineCallback**是为了让**IServiceProviderEngine**进行调用验证

代码语言:txt
复制
然后通过\*\*ServiceProviderMode\*\*这个枚举进行判断实例化的具体引擎对象,四个枚举对应四种引擎对象,前面已经说过目前DI只使用了\*\*Dynamic\*\*这一种,下面说\*\*IServiceProviderEngineCallback\*\*时也只说这一种
代码语言:txt
复制
public sealed class ServiceProvider : IServiceProvider, IDisposable, IServiceProviderEngineCallback

{

    //        ServiceProvider工作引擎接口    

    //        这个接口是一个核心接口   

    //        使用这个接口的子类进行调用缓存各种注册服务和调用访问者对象进行获取实例对象

     private readonly IServiceProviderEngine \_engine;

     

     ///         此属性缓存当前注册类型,当ServiceProviderOptions.ValidateScopes为true进行验证

     private readonly CallSiteValidator \_callSiteValidator;



     internal ServiceProvider(IEnumerable<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options)

     {

          IServiceProviderEngineCallback callback = null;

          if (options.ValidateScopes)

          {

               callback = this;

               \_callSiteValidator = new CallSiteValidator();

          }

          //        根据ServiceProviderMode进行实例化对应的工作引擎类型

          switch (options.Mode)

          {

               case ServiceProviderMode.Dynamic:

                    //      实例化 DynamicServiceProviderEngine

                    \_engine = new DynamicServiceProviderEngine(serviceDescriptors, callback);

                    break;

               case ServiceProviderMode.Runtime:

                    \_engine = new RuntimeServiceProviderEngine(serviceDescriptors, callback);

                    break;

                    case ServiceProviderMode.ILEmit:

                    \_engine = new ILEmitServiceProviderEngine(serviceDescriptors, callback);

               break;

                    case ServiceProviderMode.Expressions:

                    \_engine = new ExpressionsServiceProviderEngine(serviceDescriptors, callback);

                    break;

               default:

                   throw new NotSupportedException(nameof(options.Mode));

          }

     }



     /// 获取指定类型的服务对象

     public object GetService(Type serviceType) => \_engine.GetService(serviceType);



     public void Dispose() => \_engine.Dispose();



    void IServiceProviderEngineCallback.OnCreate(ServiceCallSite callSite)

       =>\_callSiteValidator.ValidateCallSite(callSite);



     void IServiceProviderEngineCallback.OnResolve(Type serviceType, IServiceScope scope)

      =>\_callSiteValidator.ValidateResolution(serviceType, scope, \_engine.RootScope);

}

ServiceProviderServiceExtensions

代码语言:txt
复制
前面说过这个类是`ServiceProvider`的扩展类型,提供了更佳便捷,下面就来看看这个这个扩展类提供的方法
代码语言:txt
复制
在这个扩展类中就扩展了\*\*GetRequiredService()\*\*,\*\*GetServices()\*\*和\*\*CreateScope()\*\*三个方法,前两个也是获取服务实例,第三个获取一个子`IServiceProvider`,也就是说获取一个子容器
代码语言:txt
复制
\*\*GetRequiredService()\*\*方法是如果获取的当前类型并没有被注册,那么就会抛出`InvalidOperationException`异常,从下面代码可以看出,\*\*GetRequiredService()\*\*方法首先判断当前`ServicePrivider`是否是`ISupportRequiredService`的实现类,如果是,则就返回自身的\*\*GetRequiredService()\*\*方法,如果不是,就直接调用\*\*GetService()\*\*,如果返回服务实例为\*\*NULL\*\*,就抛出异常.

ISupportRequiredService接口中只定义了**GetRequiredService()**,然而现在的ServiceProvider类型并没有实现ISupportRequiredService接口

代码语言:txt
复制
\*\*GetServices()\*\*方法是获取当前类型的所有服务实例,可以看到这个方法无非是调用的\*\*GetRequiredService()\*\*,只不过参数是一个\*\*IEnumerable<T>\*\*集合,在内部使用\*\*IEnumerable<T>\*\*参数获取服务实例是一个特殊处理,这个在后面就可以看到
代码语言:txt
复制
\*\*CreateScope()\*\*方法是一个获取子类容器的,获取方式从下面代码看的也是通过服务注册的方式获取服务实例,也就是说内部进行了注册,这个注册是在`ServiceProviderEngine`类中
代码语言:txt
复制
public static class ServiceProviderServiceExtensions

{

    //        泛型重载    

     public static T GetService<T>(this IServiceProvider provider)

          => (T)provider.GetService(typeof(T));

     

     //        如果当前服务并未注册,则会抛出异常

     public static object GetRequiredService(this IServiceProvider provider, Type serviceType)

     {

          //      如果当前ServiceProvider实现了 ISupportRequiredService 

          //      则直接调用当前ServiceProvier的GetRequiredService获取服务实例

          var requiredServiceSupportingProvider = provider as ISupportRequiredService;

          if (requiredServiceSupportingProvider != null)

             return requiredServiceSupportingProvider.GetRequiredService(serviceType);

          //      如果当前ServiceProvider未实现ISupportRequiredService

          //      就直接调用GetService获取服务实例,但是如果服务实例为空,则抛出异常

          var service = provider.GetService(serviceType);

          if (service == null)

              throw new InvalidOperationException(Resources.FormatNoServiceRegistered(serviceType));

          return service;

     }

     

    //        泛型版本

     public static T GetRequiredService<T>(this IServiceProvider provider)

          => (T)provider.GetRequiredService(typeof(T));



     //        获取指定注册类型<T>的所有服务实例

     public static IEnumerable<T> GetServices<T>(this IServiceProvider provider)

          => provider.GetRequiredService<IEnumerable<T>>();



     //        同上,

     public static IEnumerable<object> GetServices(this IServiceProvider provider, Type serviceType)

     {

          //      制造一个serviceType类型的IEnumberable<>集合,serviceTypele类型作为当前集合的泛型参数

          var genericEnumerable = typeof(IEnumerable<>).MakeGenericType(serviceType);

          return (IEnumerable<object>)provider.GetRequiredService(genericEnumerable);

     }



     //        创建一个子IServiceProvider实例

     //        内部其实将IServiceScopeFactory接口和一个ServiceScopeFactoryCallSite进行了注册

     //        这个是在IServiceProviderEngine的实现类ServiceProviderEngine中的,以后在详细介绍

     public static IServiceScope CreateScope(this IServiceProvider provider)

          => provider.GetRequiredService<IServiceScopeFactory>().CreateScope();

}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • /ServiceProvide
  • ServiceProviderServiceExtensions
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档