我正在.NET 6中使用Clean Architecture实现一个项目。根据Clean Architecture原则,我们不应该引用Web Api中的基础设施层(表示层),我们应该只访问Web Api中的应用程序层。
那么如何在不违反 Clean Architecture 原则的情况下注册基础设施层的依赖项呢?我在基础设施层创建了以下扩展方法来注册依赖项:
namespace JwtWithIdentityDemo.Infrastructure.IoC
{
public static class RegisterInfrastructure
{
public static void AddInfrastructure(this IServiceCollection services,
IConfiguration configuration)
{
services.Configure<JwtSetings>(configuration.GetSection(JwtSetings.SectionName));
services.AddSingleton<IJwtTokenGenerator, JwtTokenGenerator>();
services.AddTransient<IUserManagerWrapper, UserManagerWrapper>();
// For Identity
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddScoped<UserManager<IdentityUser>>();
// For Entity Framework
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("JwtWithIdentityDemoDb"),
sqlServerOptions => sqlServerOptions.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)
.EnableRetryOnFailure(
maxRetryCount: 5,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null)
),
ServiceLifetime.Transient
);
}
}
}
如果我在Program.cs中调用
AddInfrastructure
方法,那么我必须添加基础设施库的引用,这违反了清洁架构的原则。
var builder = WebApplication.CreateBuilder(args);
{
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<Program>());
builder.Services.AddApplication(builder.Configuration);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddInfrastructure(builder.Configuration)
}
我认为在 Web 应用程序项目中使用
AddInfrastructure
(因此添加到基础设施的链接)并不违反(在我看来)干净架构的主要原则:
内圈中的任何事物都无法了解外圈中的事物。特别是,在内圈中的代码中不得提及外圈中声明的内容的名称。
Web API 和
Infrastructure
是同一级别的概念,Program
是你的组合根。
如果你真的想变得纯粹,你可以将实际的应用程序相关的 ASP.NET Core 代码提取到一个单独的库中,并为组合根创建一个单独的项目:
MyProject.Web
和 MyProject.Infrastructure
并包含 Program
<FrameworkReference Include="Microsoft.AspNetCore.App" />
的类库,包含控制器和东西它会引入更多的仪式,但不多。