遗留C#代码重构:.NET开发者实用指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

重构遗留 C# 代码:如何将遗留项目转变为现代 .NET 产品



每个 .NET 开发者迟早都会遇到遗留代码——3000 行的单体类、.aspx.cs 文件中的意大利面条式逻辑以及散落在整个项目中的魔法字符串。重构此类代码不仅仅是"梳理"语法,而是一项战略任务:在不破坏业务逻辑的情况下改进架构。在本文中,我们将分析 C# 代码重构的实用方法,帮助您安全高效地现代化遗留项目。



1. 准备:为什么重构遗留代码需要特殊方法



新手的主要错误是立刻开始重写代码。在 C# .NET 遗留项目中,通常包含隐藏的依赖项:静态类、全局状态、通过 ADO.NET 与数据库的硬连接。任何更改都可能引发级联错误。



C# 中遗留代码的主要特征:

  • 缺少单元测试 —— 代码未被单元测试覆盖,这使重构存在风险。
  • 上帝对象 (God Objects) —— 什么都做的类:从数据库操作到 UI 渲染。
  • 硬依赖关系 —— 在方法内部直接通过 new SqlConnection() 创建实例。
  • 魔法字符串和数字 —— 硬编码在代码中的配置,而非在 app.config 或 appsettings.json 中。
  • 使用过时的 API —— 例如,使用 WebClient 而不是 HttpClient,或 ArrayList 而不是 List<T>。


在开始重构之前,务必:冻结客户的需求,设置版本控制系统 (Git),并以集成测试的形式创建"安全网"。



2. 安全重构:"绞杀藤"策略



C# 的经典技术是 Strangler Fig Pattern(绞杀藤模式)。不是立即重写所有内容,而是逐步用新组件替换旧组件,直到旧代码不再被使用。



2.1. 提取接口和依赖注入



遗留 C# 中最常见的反模式是静态助手方法。来看一个例子:



// 旧代码public class OrderService{    public void ProcessOrder(int orderId)    {        var conn = new SqlConnection("Server=myServer;Database=myDB;...");        var cmd = new SqlCommand("SELECT * FROM Orders WHERE Id = " + orderId, conn);        // ... 大量逻辑    }}


步骤 1:为数据访问提取接口。



public interface IOrderRepository{    Order GetById(int orderId);}

public class OrderRepository : IOrderRepository{ private readonly string _connectionString;

public OrderRepository(string connectionString) { _connectionString = connectionString; }

public Order GetById(int orderId) { using var conn = new SqlConnection(_connectionString); // ... 安全的查询 }}


步骤 2:通过构造函数注入依赖。现在您可以在测试中替换仓库,而 OrderService 本身不再依赖于特定的数据库实现。



public class OrderService{    private readonly IOrderRepository _orderRepository;

public OrderService(IOrderRepository orderRepository) { _orderRepository = orderRepository; }

public void ProcessOrder(int orderId) { var order = _orderRepository.GetById(orderId); // ... 业务逻辑 }}


2.2. 用现代类型替换过时类型



在 .NET Framework 中,经常使用 ArrayList、Hashtable 和 <

博客

书籍推荐