gpt4 book ai didi

c# - 默认情况下 IServiceProvider 是如何注入(inject)的?

转载 作者:行者123 更新时间:2023-12-02 18:23:43 26 4
gpt4 key购买 nike

我们可以访问 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);
}

Source

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);
}

Source

关于c# - 默认情况下 IServiceProvider 是如何注入(inject)的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70529505/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com