代码之家  ›  专栏  ›  技术社区  ›  KreonZZ

如何在标准MS DI中确定实现接口X的服务范围?

  •  0
  • KreonZZ  · 技术社区  · 6 年前

    我使用的lib是基于标准的ms-di工具(我第一次看到它,但并不熟悉)。到目前为止,它并不复杂,我建立了服务提供商:

    var services = new ServiceCollection()
                       .AddSingleton<StartupService>()
                       .AddSingleton<Service2>()
                       .AddSingleton<Service3>()
                       .AddSingleton<Service4>()
                       .BuildServiceProvider();
    

    然后我通过StartupService启动应用程序

    await services.GetService<StartupService>().InitAsync();
    

    我通过 ctor 在所有依赖这些模块或其他服务的模块中:

    private readonly Service1 service1;
    private readonly Service2 service2;
    
    public OtherService(Service1 s1, Service2 s2)
    {
        service1 = s1;
        service2 = s2;
    }
    

    到目前为止没有什么特别的,但是随着服务数量的增长,其中一些服务需要“预热”,我的StartupService开始看起来很糟糕:

    public async Task InitAsync()
    
    {
        Service1.WarmUp();
        Service2.WarmUp();
        Service3.WarmUp();
        ...
    } 
    

    所以我的想法是实施 IWarmUp 接口,就像迭代服务收集人员:

    foreach (var service in services.GetServices<IWarmUp>())
            service.WarmUp();
    

    很明显,它不起作用。

    有没有一个简单的解决方案,而不做一些复杂的系统或重写我现有的 ctors 已经注射了吗?如何获得实现特定接口的服务,以便使它们完成合同工作?

    1 回复  |  直到 6 年前
        1
  •  0
  •   thisextendsthat    6 年前

    可以将多个实现注册到单个服务类型-请参见 here . 因此,可以使用反射来查找实现 IWarmUp ,然后循环它们并将每个类型注册到该服务类型。

    foreach( var warmUpType in myListOfTypesImplementingIWarmUp )
        serviceCollection.AddTransient( typeof(IWarmUp), warmUpType )
    

    然后在 InitAsync 询问您的 IServiceProvider 对于一个 IEnumerable<IWarmUp> 循环调用 WarmUp 在每个对象上。

    您仍然可以对每个类型进行注册,就像 AddSingleton<Service2>() 然后像现在一样从DI请求它。