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

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

问题描述

我正在.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在单例容器中注册我的动态验证器,有没有一种方法可以调用一次注册在构建服务容器之后?

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容器会自动 注入到也可以通过DI解析的另一种类型(例如,控制器或过滤器)中,则em << c>提供DbAuthorizationOptions 。

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单例创建被多次调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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