C# 稍后在执行中更改服务实现(在Microsoft.Extensions.DependencyInjection中)

C# 稍后在执行中更改服务实现(在Microsoft.Extensions.DependencyInjection中),c#,.net,dependency-injection,.net-standard,microsoft.extensions.hosting,C#,.net,Dependency Injection,.net Standard,Microsoft.extensions.hosting,我有一个用例(带有登录的应用程序,以及在此之后具有不同功能的各种页面可供浏览),在该用例中,我在ConfigureServices方法中注册了我的大部分服务(通常会这样做),因此在实际(UI)执行我的程序之前 然而,我有一些服务,我只注册为傻瓜(甚至根本没有),因为这些服务应该在我登录到web服务后设置。在此登录过程中,不仅会检查用户是否有效,还会在用户验证后获取各种配置数据。其中一些数据本身需要(例如,用户货币),但其他数据用于确定应使用哪个服务实现。甚至其他数据也被用作实现本身;意味着我通过

我有一个用例(带有登录的应用程序,以及在此之后具有不同功能的各种页面可供浏览),在该用例中,我在
ConfigureServices
方法中注册了我的大部分服务(通常会这样做),因此在实际(UI)执行我的程序之前

然而,我有一些服务,我只注册为傻瓜(甚至根本没有),因为这些服务应该在我登录到web服务后设置。在此登录过程中,不仅会检查用户是否有效,还会在用户验证后获取各种配置数据。其中一些数据本身需要(例如,用户货币),但其他数据用于确定应使用哪个服务实现。甚至其他数据也被用作实现本身;意味着我通过HTTP get获取对象的实例(实现特定接口
IMyInterface
),并希望将此实例注册为
IMyInterface
的实现

然后应将这些配置数据(或相应的服务)添加回my
IServiceProvider
,以便将它们注入稍后显示的页面中。这就是我的问题所在:


在构建了
IServiceProvider
之后,有没有办法在运行时添加服务实现?
请记住,如果可能的话,我只想使用
Microsoft.Extensions.DependencyInjection
IServiceCollection
IServiceProvider
)中的内容而且没有第三方容器(我知道这在DryIoC中就是一个例子)。如果我能够在以后的执行中将
IOptions
添加到
IServiceProvider
中,那么会有部分帮助,但我更可能需要添加服务实现。

IServiceCollection
提供了一个允许工厂方法来创建服务的方法。因此,您可以将类似这样的方法添加到
ConfigureServices
方法中

services.AddTransient<IMyService>((serviceProvider) =>
{
   // You can get services you need to decide what implementation to use like so
   var someDecidingService = serviceProvider.GetService<ISomeOtherService>();

   // you can use whatever logic you need to decide what implementation to use
   if (someDecidingService.UseImplementationA())
   {
      return new ImplementationA();
   }
   else
   {
     return new ImplementationB();
   }
});
services.AddTransient((serviceProvider)=>
{
//您可以获得您需要的服务来决定使用什么样的实现
var somedecisionservice=serviceProvider.GetService();
//您可以使用您需要的任何逻辑来决定使用什么实现
if(someDecisingService.UseImplementationA())
{
返回新的实现a();
}
其他的
{
返回新的实现b();
}
});

根据您的逻辑,在容器中添加工厂类可能更有意义,因为它可以封装用于决定使用哪个服务实现的逻辑。

我认为不可能直接实现,但您可以这样做

public void ConfigureServices(IServiceCollection services)
{
    // Register the all required implementations using their implementation name
    services.AddScoped<MyService1>();
    services.AddScoped<MyService2>();
    services.AddScoped<MyService3>();

    // Decide on the required implementation at runtime and return the correct one
    services.AddScoped<IMyService>(context => 
    {
        //logic here for deciding on the implementation
        if (useService1)
        {
            return context.GetRequiredService<MyService1>();
        }
        else if (userService2)
        {
            return context.GetRequiredService<MyService2>();
        }
        
        return context.GetRequiredService<MyService3>();
    });
}
public void配置服务(IServiceCollection服务)
{
//使用实现名称注册所有必需的实现
services.addScope();
services.addScope();
services.addScope();
//在运行时决定所需的实现并返回正确的实现
services.AddScoped(上下文=>
{
//这里是决定实现的逻辑
如果(使用服务1)
{
返回context.GetRequiredService();
}
else if(userService2)
{
返回context.GetRequiredService();
}
返回context.GetRequiredService();
});
}

更好的办法是从提供者那里获得服务,如果构造函数很复杂,使用new可能会变得很麻烦,因为存在许多依赖项