C# 如何在创业课程中遵循坚实的原则?

C# 如何在创业课程中遵循坚实的原则?,c#,asp.net-core,startup,solid-principles,maintainability,C#,Asp.net Core,Startup,Solid Principles,Maintainability,AspNet Core中是否有一种本机机制,允许在单片启动类中拆分正在完成的工作,从而从长远来看提高可读性/可维护性/可伸缩性?如果是,它是如何工作的 我们有一个有点小的.Net核心MVC WebAPI项目,它抽象了一些产品目录关注点,但在我看来,Startup类正在快速增长,并且越来越难阅读和维护 以下是一些统计数字: 244行代码 32使用名称空间指令 约50行手动域级容器注册 虽然这听起来可能没什么大不了的,但与项目其余部分中遵循坚实原则的几个类相比,这可能会让人望而生畏(特别是包含的

AspNet Core中是否有一种本机机制,允许在单片
启动
类中拆分正在完成的工作,从而从长远来看提高可读性/可维护性/可伸缩性?如果是,它是如何工作的

我们有一个有点小的.Net核心MVC WebAPI项目,它抽象了一些产品目录关注点,但在我看来,
Startup
类正在快速增长,并且越来越难阅读和维护

以下是一些统计数字:

  • 244行代码
  • 32使用名称空间指令
  • 约50行手动域级容器注册
虽然这听起来可能没什么大不了的,但与项目其余部分中遵循坚实原则的几个类相比,这可能会让人望而生畏(特别是包含的不同名称空间的数量,这很好地表明了SRP违规)

我可以创建一些额外的
.AddX()
扩展方法,以减少大部分手动DI注册代码(例如,基于“每个模块”的代码或与Autofac或Structuremap中的
注册表
/
模块
非常相似的代码),但即便如此,我仍会留下大量不相关且有些复杂的逻辑,用于注册/配置以下内容:

  • Mvc(包括自定义过滤器、序列化选项、OData路由、OData EDM模型生成器)
  • 招摇过市(同样包括定制和各种设置)
  • A版本控制
  • Cors配置
  • 复杂的
    i配置
    builder使用外部配置系统
  • 显式
    IsDevelopment
    检查配置默认异常页面
这些看起来都是完全孤立的、独立的关注点,我觉得把它们放在同一个类中违反了SRP

是否有一种已知的机制可以用来将
Startup
内部所做的工作划分为不同的类,例如更紧密地遵循SRP?这样做明智吗

即使aspnet core只支持一个
Startup
类(我没有发现对此的确认),我想我也可以提出一种组合实现,使用child
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>Startup has configure method>goes to a DI bootstrapper>goes to a I命名为IocConfig.cs的文件,该文件包含复合根目录。交换容器花了几个小时,我最后一次这样做作为奖励

对于.NET Core,在内置容器时直接调用配置,请参见:

Swagger>当您安装nuget时,它应该已经给您提供了一个配置文件,在启动时再次显示w config 1行

如果.NETCore中不是这样,我仍然会手动创建配置文件并移动代码

除此之外,它做的更多的是相同的,而且语言不可知,创建一个方法或提供程序类来抽象出逻辑,并在启动时触发一两行


这里没有标准,从我可以看出,你选择走多远取决于你对代码的抽象。例如,我的oauth配置方法是startup.cs底部的方法(然后它们调用更多的类),每个方法大约有十几行,因此将它们移动到它们自己的类中没有多大意义,但是缓存单例稍微复杂一些,因此它会得到一个cachingprovider.cs文件

什么在变得艰难?是DI注册吗?这些可以(也应该)在它们自己的扩展方法中抽象出来。事实上,这同样适用于所有其他方面。DI注册是一个方面,当然会随着API本身@Tseng中的功能而增长。不过,当你说所有东西都可以重构成类似的扩展方法时,我不太确定我是否理解你的意思。如何重构我提到的MVC/Cors/OData/apiversoning/etc关注点?我的意思是,它们本身已经大部分是扩展方法了。看起来我得到了一些反对票。如果你能告诉我原因,以便我能改进这个问题,我将不胜感激。谢谢你的回答。现在还没有标记为实际答案,因为我想等待对此的定义:“从我所能说的来看,这里没有标准……”@julealgon我想你的意思是澄清……;)但我明白了。与所有设计模式一样,存在着相互竞争的问题。例如,SRP与封装竞争。所以,我在这里要说的就是使用对你手头的问题最有意义的抽象层次。提供程序类vs帮助程序方法vs内联启动代码。希望这有意义!感谢您的跟进,但我的意思是,我会等待关于aspnet核心通过本机机制支持拆分的最终答案。你的回答似乎暗示你是n