Core官方DI解析(2)-ServiceProvider

/ServiceProvide

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

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

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

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

IDisposable 说明此对象需要被释放

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

public sealed class ServiceProvider : IServiceProvider, IDisposable, IServiceProviderEngineCallback

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

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

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

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

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

然后通过\*\*ServiceProviderMode\*\*这个枚举进行判断实例化的具体引擎对象,四个枚举对应四种引擎对象,前面已经说过目前DI只使用了\*\*Dynamic\*\*这一种,下面说\*\*IServiceProviderEngineCallback\*\*时也只说这一种
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

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

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

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

}

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

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏木木玲

JVM中 对象的内存布局 以及 实例分析

2078
来自专栏大神带我来搬砖

锱铢必较:编写政治正确的代码——来聊聊java8的Optional

1928
来自专栏Coding01

轻轻玩转 Laravel Helpers 函数

在使用 Laravel 函数时,我们都避免不了使用其提供的各种各样的全局函数,也称为辅助函数。

2371
来自专栏专注 Java 基础分享

深入理解Struts2----类型转换

     之前的一系列文章主要介绍了有关Struts2的一些基本用法和部分的简单原理,但是始终没有介绍有关拦截器的相关内容,从本篇开始我们将从另一个角度去深入理...

2239
来自专栏自学笔记

python基本常识

tuple,str都可以看做是一种list,都可以进行切片操作。 利用切片操作,去掉一个字符串的前后空格。要注意是是前后空格是不止一个的,可能有很多个。

2905
来自专栏大内老A

比较一下以“反射”和“表达式”执行方法的性能差异

由于频繁地使用反射会影响性能,所以ASP.NET MVC采用了表达式树的方式来执行目标Action方法。具体来说,ASP.NET MVC会构建一个表达式来体现针...

1797
来自专栏androidBlog

java 代理模式详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/de...

1392
来自专栏数据科学

redis流计算

使用了tornado的异步和streamz的流处理两个库,需要redis 5.0以上版本

2004
来自专栏博客园

Core官方DI解析(2)-ServiceProvider

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

1072
来自专栏前端菜鸟变老鸟

截取url中的参数(支持截取一个或全部)

alert(JSON.stringify(that.getParamByUrl(url, ‘allparam’)));

1252

扫码关注云+社区

领取腾讯云代金券