为什么每次都需要调用 BuildServiceProvider 来获取依赖?

Hei*_*ich 5 c# dependency-injection ioc-container asp.net-core

在 my 上注册实例后IServiceCollection,我需要注册一个IAutomapperProvider依赖于IAssemblyProvider在此方法调用之前注册的

public static IServiceCollection RegisterAutomapperConfiguration(this IServiceCollection container, ServiceLifetime lifeTime = ServiceLifetime.Scoped)
{
        //creating the provider to get the IAssemblyProvider for my IAutomapperProvider
        var prov = container.BuildServiceProvider();
        var assemblyProvider = prov.GetService<IAssemblyProvider>();
        container.Register<IAutomapperProvider>(aProv => new AutomapperProvider(assemblyProvider), lifeTime);
        var autoMapperProvider = prov.GetService<IAutomapperProvider>();
        var mapperConfig = autoMapperProvider.GetMapperConfiguration();
        ...
}
Run Code Online (Sandbox Code Playgroud)

如果在调用之后container.Register<IAutomapperProvider>(aProv => new AutomapperProvider(assemblyProvider), lifeTime); 我不再调用 BuildServiceProvider,那么我就不会得到我之前注册的 IAutomapperProvider

public static IServiceCollection RegisterAutomapperConfiguration(this IServiceCollection container, ServiceLifetime lifeTime = ServiceLifetime.Scoped)
{
        //creating the provider to get the IAssemblyProvider for my IAutomapperProvider
        var prov = container.BuildServiceProvider();
        var assemblyProvider = prov.GetService<IAssemblyProvider>();
        container.Register<IAutomapperProvider>(aProv => new AutomapperProvider(assemblyProvider), lifeTime);
        prov = container.BuildServiceProvider();
        var autoMapperProvider = prov.GetService<IAutomapperProvider>();
        var mapperConfig = autoMapperProvider.GetMapperConfiguration();
        ...
}
Run Code Online (Sandbox Code Playgroud)

在 AspNetCore 代码中,当您调用 BuildServiceProvider 扩展方法时,它们使用相同的 IServiceCollection 可以随时间更改添加更多元素,最后您指向相同的引用

public static ServiceProvider BuildServiceProvider(this IServiceCollection services)
{
    return BuildServiceProvider(services, ServiceProviderOptions.Default);
}
Run Code Online (Sandbox Code Playgroud)

那么为什么我需要再次调用它来获得一个知道如何解析我的服务的新实例?

为了避免混淆,Register 方法是我创建的一个扩展,但在内部调用 AddSinglenton 或 Add...

  public static IServiceCollection Register<TService>(this IServiceCollection container, Func<IServiceProvider, TService> implementationFactory, ServiceLifetime lifeTime)
        where TService : class
    {

    if (container == null)
        throw new ArgumentNullException(nameof(container));
    if (implementationFactory == null)
        throw new ArgumentNullException(nameof(implementationFactory));

    switch (lifeTime)
    {
        case ServiceLifetime.Scoped:
            container.AddScoped(typeof(TService), (Func<IServiceProvider, object>)implementationFactory);
            break;
        case ServiceLifetime.Transient:
            container.AddTransient(typeof(TService), (Func<IServiceProvider, object>)implementationFactory);
            break;
        default:// ServiceLifetime.Singleton
            container.AddSingleton(typeof(TService), (Func<IServiceProvider, object>)implementationFactory);
            break;
    }

    return container;
}
Run Code Online (Sandbox Code Playgroud)

Nko*_*osi 4

BuildServiceProvider不必如此频繁地调用。

这就是实现工厂代表的用途。为此目的,他们提供对服务提供商的访问。

仍然不确定为什么您必须在第一个实例中构建提供程序,但根据当前提供的代码,在注册提供程序时使用实现工厂委托中的服务提供程序。

public static IServiceCollection RegisterAutomapperConfiguration(this IServiceCollection services, 
    ServiceLifetime lifeTime = ServiceLifetime.Scoped) {

    services.Register<IAutomapperProvider>(p => //<-- p is IServiceProvider
         //use the provider to get the IAssemblyProvider for my IAutomapperProvider
        new AutomapperProvider(p.GetService<IAssemblyProvider>()), lifeTime);
    prov = services.BuildServiceProvider();
    var autoMapperProvider = prov.GetService<IAutomapperProvider>();
    var mapperConfig = autoMapperProvider.GetMapperConfiguration();
    //...
}
Run Code Online (Sandbox Code Playgroud)

调用时BuildServiceProvider,创建的服务提供者将只知道构建集合时集合中的类型。它不会知道任何其他类型,这就是为什么它通常在注册所有类型结束时完成。