是否可以在运行时扩展 IServiceProvider

Max*_*Ast 6 c# dependency-injection asp.net-core

TLDR:IServiceProvider启动运行后是否可以修改?

我在运行时运行 dll(它实现了我的接口)。因此,有一个文件侦听器后台作业,它会等待插件 dll 被删除。现在我想将这个 dll 的类注册到依赖注入系统。因此我将IServiceCollection单例添加到 DI 里面ConfigureServices以在另一个方法中使用。

因此,我创建了一个测试项目并尝试修改ServiceCollection控制器中的 ,因为它比剥离后台作业更容易。

services.AddSingleton<IServiceCollection>(services);
Run Code Online (Sandbox Code Playgroud)

所以我添加IServiceCollection到我的控制器来检查我是否可以在Startup类运行后向 DI 添加一个类。

[Route("api/v1/test")]
public class TestController : Microsoft.AspNetCore.Mvc.Controller
{
  private readonly IServiceCollection _services;

  public TestController(IServiceCollection services)
  {
    _services = services;

    var myInterface = HttpContext.RequestServices.GetService<IMyInterface>();
    if (myInterface == null)
    {
      //check if dll exist and load it
      //....
      var implementation = new ForeignClassFromExternalDll();
      _services.AddSingleton<IMyInterface>(implementation);
    }
  }

  [HttpGet]
  public IActionResult Test()
  {
    var myInterface = HttpContext.RequestServices.GetService<IMyInterface>();
    return Json(myInterface.DoSomething());
  }
}

public interface IMyInterface { /* ... */ }

public class ForeignClassFromExternalDll : IMyInterface { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

该服务已成功加入IServiceCollection,但变化不会持续尚待HttpContext.RequestServices每次即使经过多次调用该服务数量的增加,但我没有得到被参考IServiceProvider

现在我的问题是:这是否可能实现,是的,如何实现。或者我不应该那样做?

Nko*_*osi 7

启动运行后是否可以修改 IServiceProvider?

简短的回答:

一旦IServiceCollection.BuildServiceProvider()被调用,对集合的任何更改都不会影响构建的提供程序。

使用工厂委托来推迟外部实现的加载,但这必须在启动时完成,就像注册的其余部分一样。

services.AddSingleton<IMyInterface>(_ => {
    //check if dll exist and load it
    //....
    var implementation = new ForeignClassFromExternalDll();
    return implementation;
});
Run Code Online (Sandbox Code Playgroud)

您现在可以将接口显式注入控制器构造函数中

private readonly IMyInterface myInterface;

public MyController(IMyInterface myInterface) {
    this.myInterface = myInterface;
}

[HttpGet]
public IActionResult MyAction() {
    return Json(myInterface.DoSomething());
}
Run Code Online (Sandbox Code Playgroud)

当解析控制器时解析该接口时,将调用加载 dll 逻辑。

  • [BuildServiceProvider](https://github.com/aspnet/DependencyInjection/blob/master/src/DI/ServiceCollectionContainerBuilderExtensions.cs) 是一种扩展方法,它返回一个全新的服务提供程序,然后需要将所有引用替换为整个应用程序中的旧 ServiceProvider。(包括aspnetcore、3rdparty库、你的代码等中的引用)当你可以用factroy解决它时,这似乎是不合理的。 (2认同)