c# - 如何在 Startup 课程中遵循 SOLID 原则?
问题描述
AspNet Core 中是否有一种本机机制,允许在一个单一的Startup
类中拆分正在完成的工作,以从长远来看提高可读性/可维护性/可扩展性?如果是这样,它是如何工作的?
我们有一个有点小的 .Net Core MVC WebAPI 项目,它抽象了一些产品目录问题,但是Startup
在我看来,这个类正在快速增长并且变得难以阅读和维护。
以下是一些统计数据:
- 244行代码
- 32 使用命名空间指令
- 约 50 行手动域级容器注册
虽然这听起来可能没什么大不了的,但与项目其余部分中遵循 SOLID 原则的一些类相比,这可能令人生畏(尤其是包含的不同命名空间的数量,这很好地表明了 SRP 违规)。
我可以创建一些额外的.AddX()
扩展方法来减少手动 DI 注册代码的很大一部分(例如,基于“每个模块”或非常类似于Registry
/Module
来自 Autofac 或 Structuremap 的代码),就像这里描述的那样,但即便如此我' 将留下一大堆不相关且有些复杂的逻辑,用于注册/配置内容,例如:
- Mvc(包括自定义过滤器、序列化选项、OData 路由、OData EDM 模型构建器)
- Swagger(再次包括自定义和各种设置)
- API版本控制
- Cors 配置
IConfiguration
使用外部配置系统的复杂构建器- 显式
IsDevelopment
检查配置默认异常页面
这些似乎都是完全孤立的、独立的关注点,我觉得我将它们放在同一个类中违反了 SRP。
是否有一种已知的机制可以用来将内部完成的工作拆分Startup
为单独的类,例如更紧密地遵循 SRP?那会是可取的吗?
即使 aspnet 核心仅支持单个Startup
类(我没有发现对此的确认),我想我可以提出某种复合实现,每个子Startup
类都处理这些问题之一,但我不想重新发明如果已经广泛使用并为此目的构建了类似的机制,则可能会过多地增加复杂性。
类如此之大的事实也使得拥有干净的“每个环境”配置变得更加困难,因为它会导致潜在的大量代码重复,这些配置是由约定系统本机支持的。
例如,我们在Configure
方法中有这个小代码部分:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// lots of code here
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
// ...and lots of code here
}
如果这个逻辑被抽象成一个完全隔离的配置类,我们可以有这样的东西:
public class ErrorPageConfigurationStartup
{
private readonly IApplicationBuilder _app;
public ErrorPageConfigurationStartup(IApplicationBuilder app)
{
_app = app;
}
public void Configure()
{
app.UseExceptionHandler("/Home/Error");
}
public void ConfigureDevelopment()
{
app.UseDeveloperExceptionPage();
}
}
甚至这个,利用方法级注入:
public class ErrorPageConfigurationStartup
{
public void Configure(IApplicationBuilder app)
{
app.UseExceptionHandler("/Home/Error");
}
public void ConfigureDevelopment(IApplicationBuilder app)
{
app.UseDeveloperExceptionPage();
}
}
对于上面列出的大多数问题,我可以提出类似的小类,由于减少了依赖项/责任,这将导致整体逻辑大大简化。
我正在寻找实现这一目标的方法,而无需创建大量自定义基础架构代码来支持它。
解决方案
我们的启动文件已经增长了很多,但其中大部分都被抽象到类和辅助方法后面:
DI > 启动具有配置方法 > 转到 DI 引导程序 > 转到我命名为 IocConfig.cs 的文件,其中包含复合根。上次我用这个作为奖励交换容器花了几个小时。
对于 .NET Core,配置在容器内置时直接调用,请参阅:https ://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1
Swagger > 当你安装 nuget 时,它应该已经给了你一个配置文件,在启动时再次配置 1 行。
如果在 .net Core 中不是这种情况,我仍然会手动创建配置文件并移动我的代码。
过去它都在做更多相同的事情,并且与语言无关,创建一个方法或提供程序类来抽象出逻辑并让它在启动时触发一两行。
据我所知,这里没有标准,你选择走多远取决于你抽象出代码。例如,我的 oauth 配置方法是 startup.cs 底部的方法(然后它们会调用更多类),每个方法大约有十几行,因此将它们移动到自己的类中没有多大意义,但是缓存单例有点复杂,所以它得到一个缓存提供者.cs 文件。
推荐阅读
- vba - 模板中的 PowerPoint 宏
- r - 闪亮:我正在尝试在闪亮的应用程序中绘制散点图,但它只出现一个点
- python - Python。如何将 python 数组输出保存到 Sqlite 数据库中
- amazon-web-services - S3 对象在一天中的什么时间转换到 S3-IA 或 Glacier
- vuejs2 - bootstrap-vue 数据表显示行详细信息问题
- fosuserbundle - FOSUserBundle 和 EasyAdmin - 添加新组时参数太少
- .net - WmiMonitorID - 将结果转换为 ASCII
- javascript - Cannot target a class with jQuery
- php - Magento中的反sql注入
- javascript - 如何在编译为 WebAssembly 的 Rust 库中使用 C 库?