首页 > 解决方案 > 创建新范围时添加范围服务

问题描述

IServiceProvider创建新范围时是否可以向其中添加服务?

例如,一个范围是这样创建的:

using (var scope = Services.CreateScope())
{
    // Register some service using "AddScoped"
    scope.??.AddScoped<IOrganizationIdProvider, OrganizationIdProvider>((x) => { return new OrganizationIdProvider("dynamic-parameter")});

    // Resolve service
    scope.ServiceProvider.GetService<IOrganizationIdProvider>();

}

在范围内创建新实例时应解析该服务。

标签: c#.net-coredependency-injection

解决方案


@Nkosi 已经提到,一旦创建容器,您就无法在 MS.DI 中进行新注册。但即使可以,在运行中更改容器也是一个坏主意,这就是为什么大多数 DI 容器不支持此类功能。例如,最新版本的 Autofac 和 Ninject 最近删除了此类功能,Simple Injector 文档解释了为什么它从未拥有此功能。

但是您可以通过对代码进行小的更改来实现您想要的。实现这一点的最简单方法可能是通过属性注入而不是构造函数注入来更改注入动态参数。例如:

应用程序代码的变化:

public class OrganizationIdProvider : IOrganizationIdProvider
{
    // Only required code change (notice that the interface doesn't change, this
    // property is an implementation detail)
    public string DynamicParameter { get; set; }
}

容器的配置:

// Register the implementation by itself to allow it to be requested by your infrastructure
services.AddScoped<OrganizationIdProvider>();

// Register the provider by its interface so it can be injected into application components
services.AddScoped<IOrganizationIdProvider>(c => c.GetService<OrganizationIdProvider>());

用法:

using (var scope = Services.CreateScope())
{
    // Here we resolve the OrganizationIdProvider *implementation*
    var provider = scope.ServiceProvider.GetRequiredService<OrganizationIdProvider>();

    // Set the runtime parameter
    provider.DynamicParameter = "dynamic-parameter";

    // Resolve service that might have a dependency on IOrganizationIdProvider.
    var handler =
        scope.ServiceProvider.GetRequiredService(typeof(IMessageHandler<DoSomething>));

    // Use the service
    handler.Handle(new DoSomething());
}

在处理运行时数据方面肯定有更多选择,但为此我建议您阅读关于 DI 组合模型的本系列


推荐阅读