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,有没有办法在构建服务容器后调用一次注册?
构建提供者是否会创建一个新容器,以便重新注册所有服务?
是。参见源代码。
如果是这样,我该如何调用一种方法来在现有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。这真的一切都取决于地方在它发生在应用程序的生命周期。