Loading

Core官方DI解析(2)-ServiceProvider

ServiceProvider

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集合,在内部使用IEnumerable参数获取服务实例是一个特殊处理,这个在后面就可以看到

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();
}
posted @ 2018-11-27 08:35  莫问今朝乄  阅读(5736)  评论(0编辑  收藏  举报