如何在Startup类中遵循SOLID原则?

时间:2018-11-05 21:21:41

标签: c# asp.net-core startup solid-principles maintainability

AspNet Core中是否存在一种本机机制,该机制可以将正在完成的工作拆分为一个整体的Startup类,从而从长远来看可以提高可读性/可维护性/可伸缩性?如果是这样,它如何运作?

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

以下是一些统计数据:

  • 244行代码
  • 32使用名称空间指令
  • 〜50行手动域级容器注册

尽管这听起来似乎没什么大不了,但与该项目其余部分中遵循SOLID原理的几个类相比,这可能令人生畏(尤其是所包含的不同名称空间的数量,这些都是很好地表明违反SRP的指示)。

我可以创建一些其他的.AddX()扩展方法来减少手工DI注册代码的大部分(例如,以“每个模块”为基础的内容或与Registry / {{ 1}},就像here所描述的那样,但是即使如此,我仍然会留下大量无关的,有点复杂的逻辑来注册/配置类似东西:

  • Mvc(包括自定义过滤器,序列化选项,OData路由,OData EDM模型构建器)
  • 昂首阔步(同样包括自定义和各种设置)
  • ApiVersioning
  • Cors配置
  • 使用外部配置系统的复杂Module构建器
  • 显式IConfiguration检查配置默认异常页面

这些似乎都是完全孤立的,独立的关注点,我觉得我将它们放到同一个类中来违反了SRP。

我是否可以利用一种已知的机制将IsDevelopment内完成的工作划分为单独的类,例如更紧密地遵循SRP?那是明智的吗?

即使aspnet核心仅支持单个Startup类(对此我也没有发现),我认为我可以提出一种带有子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();
    }
}

对于上面列出的大多数关注点,我可以拿出类似的小类,由于减少了依赖性/责任,这将导致总体上逻辑上更加简单。

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

1 个答案:

答案 0 :(得分:1)

我们的启动文件已经增长了很多,但是大多数文件是在类和帮助器方法之后抽象出来的:

DI>启动具有配置方法>转到DI引导程序>转到名为IocConfig.cs的文件,该文件包含复合根。上次我这样做是为了交换容器而花了几个小时。

对于.NET Core,配置是在内置容器时直接调用的,请参见:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1

Swagger>在安装nuget时,它应该已经为您提供了一个配置文件,再次在启动时使用config 1行。

如果.net Core中不是这种情况,我仍将手动创建配置文件并移动代码。

过去它们的所有功能都是相同的,并且与语言无关,创建方法或提供程序类以抽象出逻辑,并在启动时触发一两行。

据我所知,这里没有标准,您选择走多远取决于抽象代码。例如,我的oauth configure方法是startup.cs底部的方法(然后调用更多类),每个方法重约十几行,因此将它们移到自己的类上没有多大意义,但是缓存单例要复杂一些,因此它得到一个cachingprovider.cs文件。