.NET Core Singleton Creation 被多次调用 [英] .NET Core Singleton Creation is called multiple times

查看:40
本文介绍了.NET Core Singleton Creation 被多次调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 .NET Core 中将服务注册为单例.但是我看到了多次调用单例的构造函数.

I'm registering a service as a singleton in .NET Core. Yet I'm seeing the constructor for the singleton called multiple times.

services.AddSingleton<DbAuthorizationOptions, ContextAuthorizationOptions>();

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

My context authorization options is just Dictionary of Entity Types to IValidators, The context authorization options are passed into the DBContext, to automatically run validations.

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

During the registration of my services, I also register dynamic Validators with my container registered in 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);
}

我注意到当我在提供者上调用 GetService 时,我收到一个新的单例而不是现有的单例.构建提供者是否会创建一个新容器,以便重新注册所有服务?

I notice that when I call GetService on the provider I receive a new singleton instead of the existing one. Does building the provider create a new container so all of the services get re-registered?

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

If so, How can I call a method to register my dynamic validators in the singleton container with the existing IServiceProvider, is there a way to invoke some registration once after the service container is built?

推荐答案

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

Does building the provider create a new container so all of the services get reregistered?

是的.请参阅源代码.

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

If so, How can I call a method to register my dynamic validators in the singleton container with the existing IServiceProvider, is there a way to invoke some registration once after the servicecontainer is built?

我不太明白为什么这是一个问题.您应该在组合根.

I'm not really understanding why this is a problem. You should be registering all of your services one time at application startup in the Composition Root.

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

The DI container is then responsible for resolving the object graphs of the application. The application itself shouldn't have a dependency on it, nor be required to update it.

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

You should be injecting DbAuthorizationOptions in the place where you need to use it.

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

请注意,DI 容器自动提供 DbAuthorizationOptions 如果注入到另一种也通过 DI 解析的类型(例如控制器或过滤器).

Note that the DI container automatically provides the DbAuthorizationOptions if injected into another type that is also resolved through DI (such as a controller or filter).

注意:您的问题并不清楚您需要在何处执行此操作.你提到你希望它发生一次,这通常意味着将它放在应用程序启动时.但是用户无法与启动时运行的代码进行交互.因此,也许您可​​以使用 过滤器.这实际上完全取决于它必须发生在应用程序生命周期中的位置.

NOTE: It isn't very clear from your question where you need to do this. You mention that you want it to happen once, which usually means to put it at application startup. But users cannot interact with code that runs at startup. So, maybe you could use a filter. It really all depends on where in the lifecycle of the application it has to happen.

这篇关于.NET Core Singleton Creation 被多次调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆