默认情况下如何注入IServiceProvider



我们可以访问IServiceProvider作为:

public class ProductService
{
private readonly IProductRepository _productRepository;
public ProductService(IServiceProvider serviceProvider)
{
_productRepository = serviceProvider.GetRequiredService<IProductRepository>();  
}
...
}

很明显,.net默认将IServiceProvider注册为服务,但我检查了源代码:https://github.com/aspnet/Hosting/blob/master/src/Microsoft.Extensions.Hosting/HostBuilder.cs#L198

private void CreateServiceProvider() {
var services = new ServiceCollection();
services.AddSingleton(_hostingEnvironment);
services.AddSingleton(_hostBuilderContext);
services.AddSingleton(_appConfiguration); 
services.AddSingleton<IApplicationLifetime, ApplicationLifetime>();
services.AddSingleton<IHostLifetime, ConsoleLifetime>();
services.AddSingleton<IHost, Host>();
services.AddOptions();
services.AddLogging();
foreach (var configureServicesAction in _configureServicesActions) {
configureServicesAction(_hostBuilderContext, services);
}
var containerBuilder = _serviceProviderFactory.CreateBuilder(services);
foreach (var containerAction in _configureContainerActions) {
containerAction.ConfigureContainer(_hostBuilderContext, containerBuilder);
}
_appServices = _serviceProviderFactory.CreateServiceProvider(containerBuilder);   // _appServices is IServiceProvider 
if (_appServices == null) {
throw new InvalidOperationException($"The IServiceProviderFactory returned a null IServiceProvider.");
}
}

因此我们可以看到,例如:

services.AddSingleton(_appConfiguration); 

注册IConfiguration(后台的ConfigurationRoot实例(,这就是为什么我们可以在startup.cs:中使用它

public class Startup {
public Startup(IConfiguration configuration) { 
Configuration = configuration;
}
public IConfiguration Configuration { get; }

但是我在任何地方都看不到源代码寄存器_appServices(IServiceProvider(,在源代码中没有类似services.AddSingleton(_appServices);的东西

那么我们怎么还能自动访问IServiceProvider呢?或者我一定在某个地方丢失了,源代码是否在其他地方注册了IServiceProvider

BuildServiceProvider扩展最终在服务集合上调用时

/// <summary>
/// Creates a <see cref="ServiceProvider"/> containing services from the provided <see cref="IServiceCollection"/>
/// optionally enabling scope validation.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> containing service descriptors.</param>
/// <param name="options">
/// Configures various service provider behaviors.
/// </param>
/// <returns>The <see cref="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(services, options);
}

ServiceProvider实例将自己添加为一个服务。

internal ServiceProvider(ICollection<ServiceDescriptor> serviceDescriptors, ServiceProviderOptions options)
{
// note that Root needs to be set before calling GetEngine(), because the engine may need to access Root
Root = new ServiceProviderEngineScope(this, isRootScope: true);
_engine = GetEngine();
_createServiceAccessor = CreateServiceAccessor;
_realizedServices = new ConcurrentDictionary<Type, Func<ServiceProviderEngineScope, object>>();
CallSiteFactory = new CallSiteFactory(serviceDescriptors);
// The list of built in services that aren't part of the list of service descriptors
// keep this in sync with CallSiteFactory.IsService
CallSiteFactory.Add(typeof(IServiceProvider), new ServiceProviderCallSite());
CallSiteFactory.Add(typeof(IServiceScopeFactory), new ConstantCallSite(typeof(IServiceScopeFactory), Root));
CallSiteFactory.Add(typeof(IServiceProviderIsService), new ConstantCallSite(typeof(IServiceProviderIsService), CallSiteFactory));
if (options.ValidateScopes)
{
_callSiteValidator = new CallSiteValidator();
}
if (options.ValidateOnBuild)
{
List<Exception> exceptions = null;
foreach (ServiceDescriptor serviceDescriptor in serviceDescriptors)
{
try
{
ValidateService(serviceDescriptor);
}
catch (Exception e)
{
exceptions = exceptions ?? new List<Exception>();
exceptions.Add(e);
}
}
if (exceptions != null)
{
throw new AggregateException("Some services are not able to be constructed", exceptions.ToArray());
}
}
DependencyInjectionEventSource.Log.ServiceProviderBuilt(this);
}

最新更新