IServiceProvider DOTNET CORE analysis of the source code, ServiceProvider, IServiceProviderEngine, ServiceProviderEngine and ServiceProviderEngineScope

  First talk about the IServiceProvider

  IServiceProvider only to acquire the object of a function depending on the type, Imagine IOC must have a find the object, as follows

 

public interface IServiceProvider
{
  object GetService(Type serviceType);
}

  Talk about ServiceProvider

  ServiceProvider instantiates the IServiceProvider, GetService is achieved, for obtaining the actual object in the container, but it is by means of IServiceProviderEngine (This interface is again described later), as follows:

public object GetService(Type serviceType)
{
  return this._engine.GetService(serviceType);
}

  Further, there is a method ServiceCollection BuildServiceProvider (ServiceCollectionContainerBuilderExtensions present in the class), the returned object type is ServiceProvider

/// <summary>
/// Extension methods for building a <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" /> from an <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
/// </summary>
public static class ServiceCollectionContainerBuilderExtensions
{
/// <summary>
/// Creates a <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" /> containing services from the provided <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" /> containing service descriptors.</param>
/// <returns>The <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" />.</returns>
public static ServiceProvider BuildServiceProvider(
  this IServiceCollection services)
{
  return services.BuildServiceProvider(ServiceProviderOptions.Default);
}

/// <summary>
/// Creates a <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" /> containing services from the provided <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />
/// optionaly enabling scope validation.
/// </summary>
/// <param name="services">The <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" /> containing service descriptors.</param>
/// <param name="validateScopes">
/// <c>true</c> to perform check verifying that scoped services never gets resolved from root provider; otherwise <c>false</c>.
/// </param>
/// <returns>The <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" />.</returns>
public static ServiceProvider BuildServiceProvider(
  this IServiceCollection services,
  bool validateScopes)
{
  return services.BuildServiceProvider(new ServiceProviderOptions()
  {
	ValidateScopes = validateScopes
  });
}

/// <summary>
/// Creates a <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" /> containing services from the provided <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />
/// optionaly enabling scope validation.
/// </summary>
/// <param name="services">The <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" /> containing service descriptors.</param>
/// <param name="options">
/// Configures various service provider behaviors.
/// </param>
/// <returns>The <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" />.</returns>
public static ServiceProvider BuildServiceProvider(
  this IServiceCollection services,
  ServiceProviderOptions options)
{
  if (services == null)
	throw new ArgumentNullException(nameof (services));
  if (options == null)
	throw new ArgumentNullException(nameof (options));
  return new ServiceProvider((IEnumerable<ServiceDescriptor>) services, options);
}
}

  It must be combined with about IServiceProviderEngine, ServiceProviderEngine and ServiceProviderEngineScope subject to specific ServiceProvider know is how to obtain an object of the IOC container

  When using BuildServiceProvider will eventually call the new new ServiceProvider ((IEnumerable <ServiceDescriptor>) Services, Options) , and then it is to call the following function:

internal ServiceProvider(
  IEnumerable<ServiceDescriptor> serviceDescriptors,
  ServiceProviderOptions options)
{
  IServiceProviderEngineCallback callback = (IServiceProviderEngineCallback) null;
  if (options.ValidateScopes)
  {
	callback = (IServiceProviderEngineCallback) this;
	this._callSiteValidator = new CallSiteValidator();
  }
  switch (options.Mode)
  {
	case ServiceProviderMode.Dynamic:
	  this._engine = (IServiceProviderEngine) new DynamicServiceProviderEngine(serviceDescriptors, callback);
	  break;
	case ServiceProviderMode.Runtime:
	  this._engine = (IServiceProviderEngine) new RuntimeServiceProviderEngine(serviceDescriptors, callback);
	  break;
	case ServiceProviderMode.Expressions:
	  this._engine = (IServiceProviderEngine) new ExpressionsServiceProviderEngine(serviceDescriptors, callback);
	  break;
	case ServiceProviderMode.ILEmit:
	  this._engine = (IServiceProviderEngine) new ILEmitServiceProviderEngine(serviceDescriptors, callback);
	  break;
	default:
	  throw new NotSupportedException("Mode");
  }
}

  That is ultimately determined according to need ServiceProviderMode ServiceProviderEngine example of what is now a simple example DynamicServiceProviderEngine. DynamicServiceProviderEngine eventually inherit ServiceProviderEngine,

So above GetService is actually called ServiceProviderEngine of GetService

public object GetService(Type serviceType)
{
  return this.GetService(serviceType, this.Root);
}

  This.Root which is instantiated ServiceProviderScope. The above this.GetService (serviceType, this.Root) will call the following function:

 

internal object GetService(
  Type serviceType,
  ServiceProviderEngineScope serviceProviderEngineScope)
{
  if (this._disposed)
	ThrowHelper.ThrowObjectDisposedException();
  Func<ServiceProviderEngineScope, object> orAdd = this.RealizedServices.GetOrAdd(serviceType, this._createServiceAccessor);
  this._callback?.OnResolve(serviceType, (IServiceScope) serviceProviderEngineScope);
  ServiceProviderEngineScope providerEngineScope = serviceProviderEngineScope;
  return orAdd(providerEngineScope);
}

  The final call is Func <ServiceProviderEngineScope, object> orAdd = this.RealizedServices.GetOrAdd (serviceType, this._createServiceAccessor); wherein is RealizedServices The ConcurrentDictionary <the Type, Func <ServiceProviderEngineScope, Object >> RealizedServices {GET;}, this._createServiceAccessor is Func < ServiceProviderEngineScope, Object> , commissioned by the final acquisition of the object based on ServiceProviderEngineScope, that is, if there is, then you get the service from the dictionary, there is added to the queue and return directly. Further ServiceProviderEngine instantiated when instantiated this._createServiceAccessor = new Func <Type, Func <ServiceProviderEngineScope, object >> (this.CreateServiceAccessor); wherein CreateServiceAccessor is a function defined as follows:

 

private Func<ServiceProviderEngineScope, object> CreateServiceAccessor(
  Type serviceType)
{
  IServiceCallSite callSite = this.CallSiteFactory.CreateCallSite(serviceType, new CallSiteChain());
  if (callSite == null)
	return (Func<ServiceProviderEngineScope, object>) (_ => (object) null);
  this._callback?.OnCreate(callSite);
  return this.RealizeService(callSite);
}

 

  On DynamicServiceProviderEngine terms, RealizeService is defined as follows:

protected override Func<ServiceProviderEngineScope, object> RealizeService(
  IServiceCallSite callSite)
{
  int callCount = 0;
  return (Func<ServiceProviderEngineScope, object>) (scope =>
  {
	if (Interlocked.Increment(ref callCount) == 2)
	  Task.Run<Func<ServiceProviderEngineScope, object>>((Func<Func<ServiceProviderEngineScope, object>>) (() => base.RealizeService(callSite)));
	return this.RuntimeResolver.Resolve(callSite, scope);
  });
}

  RuntimeResolver is a property of ServiceProviderEngine. So far, data IOC containers can get to. Next blog will continue to explain things in this.RuntimeResover.Resolve.

 

Guess you like

Origin www.cnblogs.com/lizhizhang/p/12542602.html