.net framework-如何创建 IServiceProvider 以使用 IServiceProvider 获取已注册的服务实例?

.net framework- how to create IServiceProvider to get already registered service instance using IServiceProvider?

.NET Framework 4.6.2 应用程序中,没有内置的 DI 容器,我们使用 LightInject DI 容器来对象初始化,但不知道如何在 Main() 中创建 'IServiceProvider' 对象,以便其他 class 实现可以通过 IServiceProvider 获取已注册的服务实例,而无需使用 new关键字。

如何创建IServiceProvider对象?在 .net 框架 4.6.2 应用程序中

public class Program
{       
    public static void Main()
    {
        var container = new ServiceContainer();

        // calls below extension method
        container.RegisterDependencies();
    }
}

public static class LightInjectDIExtension
{        
    /// Registers the application dependencies.        
    public static void RegisterDependencies(this ServiceContainer container)
    {
        container.Register<IBackgroundService1, BackgroundService1>();
        container.Register<Service2>();
    }
}

一旦 IServiceProvider 实例可供使用,我打算执行以下操作

// This is background service app & this class will be 
// instantiated once in application lifetime 
public class BackgroundService1 : IBackgroundService1
{
    private readonly IServiceProvider _serviceProvider;
    public BackgroundService1(IServiceProvider serviceProvider)
    {
       _serviceProvider = serviceProvider;
    }

    public void Method1(string elementName)
    {
        // every time call to 'Method1' has to get the new instance
        // of registered 'Service2' class rather than using 'new'
        // keyword
        var service2 =  (Service2)_serviceProvider.GetService(typeof(Service2)); 
        service2.CallMe();
    }
 }

根据史蒂文的建议修改

 public class BackgroundService1 : IBackgroundService1
{
    private readonly IServiceContainer_container;
    public BackgroundService1 (IServiceContainer container)
  //Exception thrown: 'System.InvalidOperationException' in LightInject.dll
    {
       _container = container;
    }

    public void Method1(string elementName)
    {
        // every time call to 'Method1' has to get the new instance
        // of registered 'Service2' class rather than using 'new'
        // keyword
        var service2 =  (Service2)_container.GetInstance(typeof(Service2)); 
        service2.CallMe();
    }
 }

一般来说,注入 IServiceProvider(或任何允许访问未绑定依赖集的抽象是一个坏主意,因为它会导致服务定位器反模式。关于这个反模式的讨论-pattern 可以找到here.

服务定位器仅存在于 Composition Root 之外。但是,您的 BackgroundService1 可能是组合根的一部分,它可能会注入一个 DI 容器 - 或者那里的抽象 - 一个可行的解决方案。请注意,您应该努力将所有业务逻辑排除在组合根之外。这确保 BackgroundService1 纯粹作为代码的机械和平,将操作委托给 classes,运行 实际业务逻辑。

不过,在组合根内部操作时,通常不需要对 DI 容器使用抽象,例如 IServiceProvider。 Composition Root 已经拥有所有应用程序依赖项的内在知识,包括您的 DI 容器。

这意味着你可以将LightInject的ServiceContainer直接注入到BackgroundService1的构造函数中;不需要 IServiceProvider.

但是,如果您坚持使用 IServiceProvider 抽象,您可以创建一个 IServiceProvider 包装 ServiceContainer 的实现并将其 GetService 方法转发给包装ServiceContainer。这个包装器 class 可以在 ServiceContainer.

中注册