0

在没有内置 DI 容器的.NET Framework 4.6.2应用程序上,我们使用LightInject DI 容器进行对象初始化,但不知道如何在 Main() 中创建“IServiceProvider”对象,以便其他类实现可以获取已注册的服务实例 viaIServiceProvider不使用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();
    }
 }
4

1 回答 1

1

一般来说,注入一个IServiceProvider(或任何能够访问一组未绑定的依赖项的抽象是一个坏主意,因为它可能导致服务定位器反模式。关于这个反模式的讨论可以在这里找到。

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

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

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

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

于 2022-01-07T11:09:20.617 回答