当前位置:首页 > Web开发 > 正文

适合 ASP.NET Core 的超级

2024-03-31 Web开发

DRY 是那些非常重要的软件体系结构缩写之一。它的意思是“不要自我重复”,并向维护旧源代码项目的任何用户阐明了一个重要原则。也就是说,如果你在代码中自我重复,会发现每个 bug 修复和功能更新都会重复你的修改。

代码重复降低了项目的可维护性,并使应用更改变得更加困难。重复次数越多,最终得到的混乱不堪的代码就越多。另一方面,如果避免重复,最终将获得更易于维护和修复 bug 的项目,并且你将成为一名更快乐、更高效的软件开发人员。简而言之,编写 DRY 代码可以帮助创建优秀的代码。

一旦开始以 DRY 方式思考,就可以将此重要体系结构原则带到一个新层次,在该层次上,你会感觉项目从一开始便奇迹般地增长,毫不夸张地说,不需要付出任何精力来创建功能。对于缺乏经验的人来说,代码似乎是通过“超级 DRY”机制凭空出现的。 优秀的代码几乎总是很小,但出色的代码更小。

在本文中,我将介绍超级 DRY 开发的神奇之处,以及多年来我使用的一些技巧,它们可以帮助你轻松创建 ASP.NET Core Web API。本文中的所有内容都基于通用解决方案和 DRY 代码的概念,并且只使用来自我们行业的最佳做法。但首先是一些背景理论。

CRUD、HTTP REST 和 SQL

Create、Read、Update 和 Delete (CRUD) 是大多数数据模型的基础行为。在大多数情况下,数据实体类型需要这四个操作,事实上 HTTP 和 SQL 都是围绕它们生成的。HTTP POST 用于创建项目,HTTP GET 用于读取项目,HTTP PUT 用于更新项目,HTTP DELETE 用于删除项目。SQL 同样围绕 CRUD 发展,包括 insert、select、update 和 delete。一旦对此进行一些思考,就会发现它基本上都是关于 CRUD,假设你不想“全力以赴”并实现 CQRS 体系结构。

这样,你就有了必要的语言机制来讨论 HTTP 谓词,它们可以从客户端的 HTTP 层通过 C# 代码一直传播到关系数据库。现在,你需要的是一种通用方法来通过层实现这些想法。并且你希望通过出色的体系结构基础在不自我重复的情况下完成此操作。下面我们就开始。

首先,在 github.com/polterguy/magic/releases 下载代码。解压缩文件并在 Visual Studio 中打开 magic.sln。启动调试器,并注意在 Swagger UI 中已经有五个 HTTP REST 终结点。这些 HTTP 终结点来自何处?让我们来看一下代码,因为这个问题的答案可能会让你大吃一惊。

你看,没有代码!

当你开始浏览代码时,首先会注意到 ASP.NET Core Web 项目本身实际上是空的。这可能是由于 ASP.NET Core 功能,该功能允许你动态地包含控制器。如果想了解它背后的内部机制,可以查看 Startup.cs 文件。大体而言,它是从文件夹的所有程序集中动态地将每个控制器添加到 AppDomain。这个简单的想法让你可以重用控制器,并在编写解决方案时以模块化的方式进行思考。跨多个项目重用控制器的能力是成为超级 DRY 实践者的第一步。

打开 web/controller/magic.todo.web.controller,然后查看 TodoController.cs 文件。你会发现它是空的。那么这五个 HTTP REST 终结点来自何处?答案是通过面向对象的编程 (OOP) 和 C# 泛型机制。TodoController 类继承自 CrudController,传递视图模型及其数据库模型。此外,它还使用依赖关系注入来创建 ITodoService 实例,并将其移交给 CrudController 基类。

因为 ITodoService 接口从 ICrudService 继承了正确的泛型类,所以 CrudController 基类会乐于接受你的服务实例。此外,此时它已经可以多态地使用服务,就像它是一个简单的 ICrudService 一样,当然 ICrudService 是一个带有参数化类型的泛型接口。这提供了对 CrudController 中五个通用定义的服务方法的访问。要理解其含义,请认识到,使用下面的简单代码,你实际上已经创建了所需的所有 CRUD 操作,并将它们从 HTTP REST 层通过服务层传播到域类层次结构,最后到达关系数据库层。下面是控制器终结点的整个代码:

[Route("api/todo")]
public class TodoController : CrudController<Todo, db.Todo>
{
  public TodoController(ITodoService service)
    : base(service)
  { }
}

此代码提供五个 HTTP REST 终结点,允许你创建、读取、更新、删除和计数数据库项,这简直是奇迹。整个代码均“已声明”,并且不包含任何一行功能。当然,,代码本身不会生成,而且大部分工作都是在幕后完成的,但此处的代码已经成为“超级 DRY”。 使用更高级别的抽象具有真正的优势。一个贴切的例子是 C# if-then 语句和基础程序集语言代码之间的关系。我所概述的方法只是比硬编码控制器代码更高层次的抽象。

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/43061.html