首页 > 解决方案 > 如何在 Startup 课程中遵循 SOLID 原则?

问题描述

AspNet Core 中是否有一种本机机制,允许在一个单一的Startup类中拆分正在完成的工作,以从长远来看提高可读性/可维护性/可扩展性?如果是这样,它是如何工作的?

我们有一个有点小的 .Net Core MVC WebAPI 项目,它抽象了一些产品目录问题,但是Startup在我看来,这个类正在快速增长并且变得难以阅读和维护。

以下是一些统计数据:

虽然这听起来可能没什么大不了的,但与项目其余部分中遵循 SOLID 原则的一些类相比,这可能令人生畏(尤其是包含的不同命名空间的数量,这很好地表明了 SRP 违规)。

我可以创建一些额外的.AddX()扩展方法来减少手动 DI 注册代码的很大一部分(例如,基于“每个模块”或非常类似于Registry/Module来自 Autofac 或 Structuremap 的代码),就像这里描述的那样,但即便如此我' 将留下一大堆不相关且有些复杂的逻辑,用于注册/配置内容,例如:

这些似乎都是完全孤立的、独立的关注点,我觉得我将它们放在同一个类中违反了 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();
    }
}

对于上面列出的大多数问题,我可以提出类似的小类,由于减少了依赖项/责任,这将导致整体逻辑大大简化。

我正在寻找实现这一目标的方法,而无需创建大量自定义基础架构代码来支持它。

标签: c#asp.net-corestartupsolid-principlesmaintainability

解决方案


我们的启动文件已经增长了很多,但其中大部分都被抽象到类和辅助方法后面:

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 文件。


推荐阅读