Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在运行时通过DI注册服务?_C#_Asp.net Core_Asp.net Core Mvc_.net Core - Fatal编程技术网

C# 在运行时通过DI注册服务?

C# 在运行时通过DI注册服务?,c#,asp.net-core,asp.net-core-mvc,.net-core,C#,Asp.net Core,Asp.net Core Mvc,.net Core,我正在使用ASP.NET Core,希望在运行时向IServiceProvider添加一个服务,以便通过DI在整个应用程序中使用它 例如,一个简单的示例是,用户转到设置控制器并将身份验证设置从“开”更改为“关”。在这种情况下,我希望替换在运行时注册的服务 services.AddTransient<AuthenticationService>(); services.AddTransient<NoAuthService>(); services.AddTransient&

我正在使用ASP.NET Core,希望在运行时向IServiceProvider添加一个服务,以便通过DI在整个应用程序中使用它

例如,一个简单的示例是,用户转到设置控制器并将身份验证设置从“开”更改为“关”。在这种情况下,我希望替换在运行时注册的服务

services.AddTransient<AuthenticationService>();
services.AddTransient<NoAuthService>();
services.AddTransient<IAuthenticationServiceFactory, AuthenticationServiceFactory>();
设置控制器中的Psuedo代码:

if(settings.Authentication == false)
{
     services.Remove(ServiceDescriptor.Transient<IAuthenticationService, AuthenticationService>());
     services.Add(ServiceDescriptor.Transient<IAuthenticationService, NoAuthService>());
}
else
{
     services.Remove(ServiceDescriptor.Transient<IAuthenticationService, NoAuthService>
     services.Add(ServiceDescriptor.Transient<IAuthenticationService, AuthenticationService>());
}
if(settings.Authentication==false)
{
Remove(servicescriptor.Transient());
Add(servicescriptor.Transient());
}
其他的
{
删除(servicescriptor.Transient)
Add(servicescriptor.Transient());
}

当我在Startup.cs中执行此操作时,此逻辑工作正常,因为IServiceCollection尚未内置到IServiceProvider中。但是,我希望在启动已执行后能够执行此操作。有人知道这是否可行吗?

我将创建一个服务工厂,而不是在运行时注册/删除服务hich在运行时决定正确的服务

services.AddTransient<AuthenticationService>();
services.AddTransient<NoAuthService>();
services.AddTransient<IAuthenticationServiceFactory, AuthenticationServiceFactory>();
类中的用法:

public class SomeClass
{
    public SomeClass(IAuthenticationServiceFactory _authenticationServiceFactory)
    {
        var authenticationService = _authenticationServiceFactory.GetAuthenticationService();
    }
}

@Dawid你说这是什么权威的“正确的方法”?你的意思是“我也会这样做”?为什么?为什么这是一个好答案?因为从设计模式的角度来看,注册工厂隐藏一些细节更好(在这种情况下,获得一些配置/设置)并且只提供正确的实现。谢谢,但我认为这对我不起作用。为了说明这个概念,我将我的示例非常简单,但这不是我的实际问题。我有一个模块化系统,可以“安装”插件在运行时,这些插件有需要添加到ServiceCollection的服务。我的问题是,我没有找到一种在运行时添加这些服务的令人满意的方法。感谢您花时间响应!@CodeCaster:
ServiceCollection
也不应该在引导后更改。该提供程序是在en ASP.NET核心调用
services.buildServiceProvider()
(在
ConfigureServices
之后和
Configure
调用之前的某个地方),对
IServiceCollection
的更改无关紧要,再次调用
.buildServiceProvider()
只是创建了一个新的提供者,旧的提供者仍然在singleton服务中被引用,这在change@A.Fry:无论是否在运行时,您都需要重新启动应用程序才能执行此操作。或者使用允许在运行时更改依赖项的容器。正如您在此处看到的,ServiceProvider是内部的,没有公共的更改其
ServiceTable
集合的方法