.NET Core Singleton Creation被多次调用

joh*_*y 5 9 c# dependency-injection .net-core asp.net-core

我正在将服务注册为.NET Core中的单例.然而,我正在看多次调用单例的构造函数.

services.AddSingleton<DbAuthorizationOptions, ContextAuthorizationOptions>();
Run Code Online (Sandbox Code Playgroud)

我的上下文授权选项只是实体类型字典IValidators,上下文授权选项被传递到DBContext自动运行验证.

在我的服务注册期间,我还注册了在DI中注册的容器的动态验证器.

var useDynamicValidator = serviceOption.ValidatorOptions != null;
if(useDynamicValidator)
{
    //TODO: Extract this to before the register service no sense in building the provider each time
    //TODO: Make this cleaner don't be dependent on Authorization options
    var provider = services.BuildServiceProvider();
    var authOptions = provider.GetService<DbAuthorizationOptions>();
    var validator = BuildDynamicValidatorFactory(serviceOption).Invoke(provider, null);
    authOptions.ValidatorOptions.AddValidatorForSet(validator);
}
Run Code Online (Sandbox Code Playgroud)

我注意到,当我打电话GetService给提供者时,我会收到一个新的单例,而不是现有的单例.构建提供程序是否会创建一个新容器,以便重新注册所有服务?

如果是这样,我如何调用一个方法在现有的单例容器中注册我的动态验证器IServiceProvider,有没有办法在构建服务容器后调用一次注册?

Nig*_*888 5

构建提供者是否会创建一个新容器,以便重新注册所有服务?

是。参见源代码

如果是这样,我该如何调用一种方法来在现有IServiceProvider的单例容器中注册我的动态验证器,是否可以在构建servicecontainer之后调用一次注册?

我不是很了解为什么这是一个问题。您应该在应用程序启动时一次Composition Root中注册所有服务。

然后,DI容器负责解析应用程序的对象图。应用程序本身不应该依赖它,也不需要更新它。

您应该在需要使用它的地方注射 DbAuthorizationOptions

public class Foo : IFoo
{
    private readonly DbAuthorizationOptions authOptions;

    public Foo(DbAuthorizationOptions authOptions) // <-- Inject parameters
    {
        this.authOptions = authOptions ??
            throw new ArgumentNullException(nameof(authOptions));
    }

    public void DoSomething()
    {
        // TODO: Inject the type that has the BuildDynamicValidatorFactory
        // method and the serviceOption (whatever type that is) here
        // either as a method parameter of this method, or a constructor
        // parameter of this class.
        var validator = BuildDynamicValidatorFactory(serviceOption).Invoke(provider, null);
        // Now we have an instance of authOptions that can be used
        authOptions.ValidatorOptions.AddValidatorForSet(validator);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,DI容器会自动提供DbAuthorizationOptionsif注入是否也可以通过DI解析的另一种类型(例如控制器或过滤器)。

注意:从您的问题尚不清楚,您需要在哪里执行此操作。您提到您希望它发生一次,这通常意味着将其放在应用程序启动时。但是用户无法与启动时运行的代码进行交互。因此,也许您可​​以使用filter。这真的一切都取决于地方在它发生在应用程序的生命周期。