繁体   English   中英

.NET Core单例创建被多次调用

[英].NET Core Singleton Creation is called multiple times

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

services.AddSingleton<DbAuthorizationOptions, ContextAuthorizationOptions>();

我的上下文授权选项只是将实体类型字典发送给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);
}

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

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

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

是。 参见源代码

如果是这样,我该如何调用一种方法来向现有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);
    }
}

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

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

您可以声明对IServiceProvider的依赖关系-不要构建它,注入它。

public class SomeController
{
    DbAuthorizationOptions authOptions;
    public SomeController(IServiceProvider provider)
    {
        authOptions = provider.GetSerivce<DbAuthorizationOptions>();
    }
}

但这是服务定位器的反模式。 在您提供了更多详细信息之后,我对NightOwl888的帖子发表了评论时,工厂可能是一个更好的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM