警告:看完这篇文章,你可能要重写一半代码库

作者:微信公众号:【架构师老卢】
7-1 8:51
18

我构建.NET系统已有17年以上——从初创公司到企业级应用,再到复杂的单体系统。这里有一个残酷的事实:

"我们遇到的大部分代码问题并非源于.NET本身...而是因为我们没有正确使用合适的工具。"

🚀 1. FluentValidation:让代码像英语一样易读

自然流畅的验证代码,编写、阅读和维护都变得轻松。

public class OrderValidator : AbstractValidator<Order>
{
    public OrderValidator()
    {
        RuleFor(x => x.Amount).GreaterThan(0).WithMessage("金额必须为正数");
        RuleFor(x => x.CustomerEmail).NotEmpty().EmailAddress();
        RuleFor(x => x.OrderDate).LessThanOrEqualTo(DateTime.UtcNow).WithMessage("不允许未来日期的订单");
    }
}

我为什么爱它

  • 声明式、流畅的API——远胜于if语句树
  • 与业务逻辑清晰分离
  • 自动与ASP.NET Core集成

📌 适用场景:当你的模型包含10+验证规则时

⚠️ 不适用场景:在紧密循环中需要超低延迟性能时

⚡ 2. Mapster:最快的对象映射器之一

var dto = user.Adapt<UserDto>();

一行代码。零配置。闪电般快速。

我为什么爱它

  • 使用Adapt<T>()实现零配置映射
  • 比AutoMapper更快——有基准测试为证。因为Mapster使用编译时代码生成,而AutoMapper基于运行时反射
  • 支持LINQ投影、嵌套映射等

📌 适用场景:当你在10+个DTO和领域实体间映射,想要干净快速的转换而不需要臃肿的配置时

🛡️ 3. Polly:无需模板代码的弹性策略

var result = await Policy
    .Handle<HttpRequestException>()
    .RetryAsync(3)
    .ExecuteAsync(() => _httpClient.GetAsync(url));

一行代码将脆弱的HTTP调用变成经过战斗考验的战士。

我为什么爱它:一行代码实现弹性——重试、断路器、超时、回退

💡 使用案例:带随机退避的重试

var retryPolicy = Policy
    .Handle<HttpRequestException>()
    .WaitAndRetryAsync(
        3,
        retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) + TimeSpan.FromMilliseconds(Random.Shared.Next(0, 100)),
        onRetry: (exception, timeSpan, retryCount, context) =>
        {
            _logger.LogWarning($"第{retryCount}次重试,等待{timeSpan.TotalSeconds}秒,原因:{exception.Message}");
        });

var response = await retryPolicy.ExecuteAsync(() => _httpClient.GetAsync("https://api.example.com/data"));

📌 适用场景:当你调用容易出现问题的第三方服务或内部微服务时

💬 4. Refit:接口→REST客户端

仅用接口自动生成REST客户端

public interface IMyApi
{
    [Get("/users/{id}")]
    Task<User> GetUserAsync(int id);
}

var api = RestService.For<IMyApi>("https://api.example.com");

我为什么爱它

  • 仅需接口就能生成完整的REST客户端
  • 不再需要HttpClient模板代码

🔍 示例用例:简洁调用外部API

public interface IGitHubApi
{
    [Get("/users/{username}")]
    Task<GitHubUser> GetUser(string username);
}

var client = RestService.For<IGitHubApi>("https://api.github.com");

var user = await client.GetUser("dotnet");
Console.WriteLine(user.Name);

无需手动编写HTTP头、解析JSON或处理状态码。

📌 适用场景:当你需要消费2+个REST API并希望减少模板代码、提高生产力时

🧠 5. MediatR:无繁文缛节的CQRS

public record GetUserQuery(int Id) : IRequest<User>;

public class GetUserHandler : IRequestHandler<GetUserQuery, User>
{
    public Task<User> Handle(GetUserQuery request, CancellationToken ct)
        => _userService.GetByIdAsync(request.Id);
}

我为什么爱它:促进垂直切片架构、关注点分离和基于处理器的可测试性

🔍 示例用例:模块化用户查询和命令

public record UpdateUserCommand(int Id, string Email) : IRequest;

public class UpdateUserHandler : IRequestHandler<UpdateUserCommand>
{
    public async Task Handle(UpdateUserCommand cmd, CancellationToken ct)
    {
        var user = await _db.Users.FindAsync(cmd.Id);
        user.Email = cmd.Email;
        await _db.SaveChangesAsync();
    }
}

现在你的更新逻辑存在于UpdateUserCommand中,而不是深埋在UserService的6个不相关方法下。

📌 适用场景:当你厌倦了上帝服务并想要真正的关注点分离,或实现CQRS时

🧪 6. Bogus:逼真的假数据

var faker = new Faker<User>()
    .RuleFor(u => u.Name, f => f.Name.FullName())
    .RuleFor(u => u.Email, f => f.Internet.Email());

我为什么爱它:加速测试、填充开发数据库、无需真实用户即可进行压力测试

🔍 示例用例:为负载测试生成1000个假用户

var users = new Faker<User>()
    .RuleFor(u => u.Id, f => Guid.NewGuid())
    .RuleFor(u => u.Name, f => f.Name.FullName())
    .RuleFor(u => u.Email, f => f.Internet.Email())
    .Generate(1000);

将其导入你的EF Core种子数据或MongoDB插入——瞬间就能获得填充好的测试数据库。

📌 适用场景:编写单元测试、集成测试或填充开发环境时

📊 7. BenchmarkDotNet

像单元测试一样的性能分析

[Benchmark]
public void ParseWithSpan()
{
    var value = int.Parse("123");
}

普通开发者靠猜测。优秀开发者靠测量。

我为什么爱它

  • 细粒度的性能测量
  • 微软自己也用它来基准测试.NET Core

🔍 示例用例:比较3种数字解析方法

[MemoryDiagnoser]
public class ParsingBenchmarks
{
    [Benchmark]
    public int ParseInt() => int.Parse("123");

    [Benchmark]
    public int ConvertInt() => Convert.ToInt32("123");

    [Benchmark]
    public int TryParseInt()
    {
        int.TryParse("123", out var result);
        return result;
    }
}

运行后,BenchmarkDotNet会给你并列对比:

  • 执行时间
  • 标准差
  • 分配字节数
  • Gen0/Gen1/Gen2垃圾回收
相关留言评论
昵称:
邮箱:
阅读排行