我正在重构ASP.Net Core 2.2 webapp。我决定将一些功能移到一个单独的类库(.net core 2.2)项目中。该类库对System.IO.Abstractions具有依赖关系(因此可以进行单元测试)。类库的简化版本如下所示:
using System;
using System.IO.Abstractions;
namespace ClassLibrary1
{
public class TestService
{
private IFileSystem fileSystem;
internal TestService(IFileSystem fileSystem)
{
this.fileSystem = fileSystem;
}
public TestService() : this(new FileSystem()) {}
}
}
在Web应用程序项目中,我添加了对类库dll的引用。在Startup.cs中,我添加了using语句,在ConfigureServices中,我在DI容器中注册了TestService(在类库中定义):
...
using ClassLibrary1;
namespace WebApplication1
{
public class Startup
{
...
public void ConfigureServices(IServiceCollection services)
{
...
services.AddScoped<TestService>();
}
...
}
}
我正在尝试在控制器中实例化服务,如下所示:
using ClassLibrary1;
namespace WebApplication1.Controllers
{
public class HomeController : Controller
{
TestService service;
public HomeController(TestService service)
{
this.service = service;
}
...
}
}
当我运行此项目时,出现以下错误:
FileNotFoundException:无法加载文件或程序集'System.IO.Abstractions,版本= 7.0.0.0,文化=中性,PublicKeyToken = 96bf224d23c43e59'。系统找不到文件指定。
我如何解决此问题而不将System.IO.Abstractions包添加到webapp项目中?
我的理解是,出现问题是因为我正尝试使用DI解析的类的构造函数包含IFileSystem类型,该类型是外部依赖项,因此webapp无法解决它。
在寻找解决此问题的方法后,我试图做的一件事是在类库中添加扩展方法,该方法负责注册所需的依赖项:
using Microsoft.Extensions.DependencyInjection;
using System.IO.Abstractions;
namespace ClassLibrary1
{
public static class IServiceCollectionExtension
{
public static IServiceCollection AddTestService(this IServiceCollection services)
{
services.AddScoped<IFileSystem, FileSystem>();
services.AddScoped<TestService>();
return services;
}
}
}
然后在Webapp的ConfigureServices中使用此扩展方法,如下所示:
services.AddTestService();
但是这会导致相同的错误消息。
编辑:
我真正的问题是如何正确编写类库,以便可以使用它而不必担心依赖关系?
因此,在webapp中,应该使用公共的无参数构造函数实例化TestService,并且在xunit项目的classlib解决方案中,可以使用内部构造函数实例化TestService。
您不应该解析类库中的依赖项。 The composition root只能在主应用程序中。合成根是应用程序生命周期中可以设置对象图的起点和最早点。
因此Startup.cs
是ASP.NET Core应用程序中的合成根。
services.AddScoped<IFileSystem, FileSystem>();
类库没有合成根。