如何从Startup中配置的容器中解析类库中的依赖项?

时间:2018-06-05 18:53:26

标签: c# unit-testing asp.net-core dependency-injection mocking

目标是使用IoC并能够[模拟依赖关系]进行单元测试。

项目:具有多个类库的.NET Core Web API

我正在为我的IoC使用Microsoft.Extensions.DependencyInjection,如果它支持我想要完成的任务,我想继续使用它。

问题:我的程序集(类库)中至少有一个类具有需要模拟的依赖项(例如使用Moq)。我完全理解我可以使用构造函数注入来注入接口,但这不符合方案。

我在程序集中尝试完成的工作是使用我在Web API的Startup类中启动的容器来解决依赖关系。

我该怎么做?如果这是不可能的,那么可能是另一种完成同样事情的方法,即在不使用依赖注入的情况下模拟我的打印机?

下面是一些示例代码,希望能够澄清一点。

Web API的Startup.cs(引用了定义打印机的程序集)

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IPrinter, Printer>();
}

在另一个程序集中,我想使用同一个容器解析一个Printer实例。

    public interface IPrinter
    {
        void Print(string text);
    }

    public class Printer : IPrinter
    {
        public void Print(string text)
        {
            Console.WriteLine("Printing: " + text);
        }
    }


    public class Task
    {
        public void PrintSomething(string text)
        {
            //do not 'new up' but resolve it from the container of Startup.cs
            var printer = new Printer(); 
            printer.Print(text);
        }
    }

1 个答案:

答案 0 :(得分:2)

这是一个隐藏在XY problem背后的设计问题。

您已经击落了The Explicit Dependencies Principle

  

方法和类应明确要求(通常通过方法参数或构造函数参数)所需的任何协作对象才能正常运行。

public class PrintTask {
    private readonly IPrinter printer;

    public PrintTask(IPrinter printer) {
        this.printer = printer;
    }

    public void PrintSomething(string text) {
        printer.Print(text);
    }
}

哪个允许依赖类,已经在容器中注册

public void ConfigureServices(IServiceCollection services) {
    services.AddScoped<IPrinter, Printer>();
    services.AddScoped<PrintTask>();
}

来自一个灵活的解耦类,其依赖关系可以很容易地被模拟和注入。

依赖注入是最好的选择,但也有服务定位器反模式,虽然可行,但通常不建议。