将依赖注入添加到 .NET 控制台应用程序(和测试)





5.00/5 (1投票)
如何在 .NET 控制台应用程序中添加 DI
您可能已经注意到,依赖注入 (DI) 如今已成为事实上的标准,并且可以说理所当然,因为它(如果使用得当)会产生可测试、可更改、解耦的代码库。 但也许一个挑战(至少在 ASP.NET 生态系统中)是,当我们创建一个新的 ASP.NET 项目时,很多引导程序都得到了照顾,因此在自动化测试或其他顶级项目中设置 DI 可能会令人困惑和不清楚,这些项目没有获得 ASP.NET Web 项目提供的开箱即用的脚手架。 关于如何执行此操作的指南有很多,但这是一个简洁明了的指南。
哦,在进一步讨论之前,我想提一下,这里显示的示例将使用 Microsoft 提供的、与 ASP.NET Core 项目一起提供的简单 DI 容器。 这里涵盖的概念与其他容器类似,但代码本身会略有不同。
首先,让我们订购一些包
在版本控制方面,您很可能已经在解决方案中的其他项目中安装了这些包。 因此,只要您没有在项目之间混合和匹配 .NET 版本,保持版本相同是有意义的。 因此,我将只列出您需要的软件包,并让您找出合适的版本。
Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.Json
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.DependencyInjection.Abstractions
Microsoft.Extensions.Options
添加您的应用程序设置
在配置方面,您可能在现有 ASP.NET Web 项目中的 appsettings.*.json 文件中定义了一些自定义应用程序设置。 您需要将其添加到新的(简陋的)项目中,以便应用相同的设置。 您有几个选项可以执行此操作
- 为您的新项目创建一个自定义设置文件;
- 将现有的 appsettings.json 文件从您的 Web 项目复制到您的新项目;或
- 从现有的 appsettings.json 文件添加链接到您的新项目
我通常更喜欢选项 3,因此您在主 Web 项目的 appsetting.json 文件中所做的任何更改也会在您的新项目中生效,并且您无需维护两个(或更多)config 文件。
* 在 Rider 或 VS for Mac 中,此外观可能略有不同,但它应该仍然存在。
全部设置好
在这里,我建议创建一个 xxxBootstrapper
类来处理 DI 容器的引导程序和任何其他设置,其中 xxx
是您的项目的前缀。 例如,如果这是一个测试项目,您可以将其称为 TestBootstrapper
。
例如
public static class TestBootstrapper
{
public static void Bootstrap(IServiceCollection services)
{
// todo: Add any test services
}
}
太好了,但我实际上如何创建 Iservicecollection 实例?
礼貌地询问 :) 严肃地说,只需创建一个新的 ServiceCollection
,它是 IServiceCollection
的具体实现。
public static class ServiceProviderFactory
{
public static IServiceProvider CreateServiceProvider()
{
var services = new ServiceCollection();
LibraryBootstrapper.Bootstrap(services);
TestBootstrapper.Bootstrap(services);
return services.BuildServiceProvider();
}
}
由于我们可能会在每个测试中执行此操作,并且引导逻辑可能会随着解决方案的增长而增长,因此为了方便起见,我将其放置在工厂内部。
整合
这是它。 :) 请注意,Setup
和 Test
是 NUnit 特定的属性,它们可能与您根据所使用的测试框架需要使用的属性不同 - 尽管您应该使用 NUnit,因为所有其他属性都很愚蠢。
*** 以上声明只是一个玩笑。 使用您喜欢的任何测试框架。
using ConsoleDependencyInjection.Library;
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleDependencyInjection.Tests;
public class MyServiceTests
{
private IMyService _sut;
[SetUp]
public void Setup()
{
_sut = ServiceProviderFactory
.CreateServiceProvider()
.GetService<IMyService>();
}
[Test]
public void Test1()
{
Assert.DoesNotThrow(() =>
{
_sut.DoTheThing();
});
}
}
在 Setup
方法(在每个测试之前运行)中,我们从我们之前创建的工厂创建一个服务提供程序的实例,并使用 Service Locator 方法进行 DI,要求提供程序提供我们要测试的服务。 要查看整个过程的实际效果,您可以查看 Github 上的存储库。
感谢您的阅读! 再见!