You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Fast Endpoints中复用处理器,减少.NET 9 WebAPI重复代码?

复用Fast Endpoints CRUD端点逻辑的解决方案

针对你遇到的重复代码问题,最直接高效的方式是封装泛型基类,将通用的CRUD逻辑抽离出来,具体端点只需继承基类并指定必要的类型和配置参数即可。以下是具体实现步骤:

1. 创建泛型基类(以Get单条数据为例)

这个基类将包含通用的路由配置、数据查询、结果映射和响应逻辑:

public abstract class GetEntityEndpoint<TEntity, TDto>(
    PostgresD db, 
    IMapper mapper, 
    ILogger logger) : EndpointWithoutRequest<TDto>
    where TEntity : class
{
    // 由子类提供路由模板(例如"/contact/{id:Guid}")
    protected abstract string RouteTemplate { get; }

    public override void Configure()
    {
        Get(RouteTemplate);
        // 可在这里添加通用的权限验证、请求验证等配置
    }

    public override async Task HandleAsync(CancellationToken ct)
    {
        var id = Route<Guid>("id");
        var entity = await db.FindAsync<TEntity>(id, ct);

        if (entity is null)
        {
            await SendNotFoundAsync(ct);
            return;
        }

        Response = mapper.Map<TDto>(entity);
        logger.LogInformation("获取实体 {EntityType}(ID: {Id})成功", typeof(TEntity).Name, id);
    }
}

2. 简化具体端点实现

原来的GetContact端点只需继承基类,提供路由模板即可:

public class GetContact(PostgresD db, IMapper mapper, ILogger<GetContact> logger) 
    : GetEntityEndpoint<Contact, ContactDto>(db, mapper, logger)
{
    protected override string RouteTemplate => "/contact/{id:Guid}";
}

3. 扩展到其他CRUD操作

用同样的思路可以封装其他CRUD的泛型基类,比如获取列表、创建、更新、删除:

示例:获取列表的泛型基类

public abstract class GetEntityListEndpoint<TEntity, TDto>(
    PostgresD db, 
    IMapper mapper, 
    ILogger logger) : EndpointWithoutRequest<List<TDto>>
    where TEntity : class
{
    protected abstract string RouteTemplate { get; }

    public override void Configure()
    {
        Get(RouteTemplate);
    }

    public override async Task HandleAsync(CancellationToken ct)
    {
        var entities = await db.Set<TEntity>().ToListAsync(ct);
        Response = mapper.Map<List<TDto>>(entities);
        logger.LogInformation("获取 {EntityType} 列表成功,共 {Count} 条", typeof(TEntity).Name, entities.Count);
    }
}

示例:创建实体的泛型基类

public abstract class CreateEntityEndpoint<TEntity, TRequest, TDto>(
    PostgresD db, 
    IMapper mapper, 
    ILogger logger) : Endpoint<TRequest, TDto>
    where TEntity : class
{
    protected abstract string RouteTemplate { get; }

    public override void Configure()
    {
        Post(RouteTemplate);
        AllowAnonymous(); // 根据实际需求调整权限
    }

    public override async Task HandleAsync(TRequest req, CancellationToken ct)
    {
        var entity = mapper.Map<TEntity>(req);
        db.Add(entity);
        await db.SaveChangesAsync(ct);
        
        Response = mapper.Map<TDto>(entity);
        logger.LogInformation("创建 {EntityType} 成功,ID: {Id}", typeof(TEntity).Name, typeof(TEntity).GetProperty("Id")?.GetValue(entity));
    }
}

关键优势

  • 彻底消除重复代码,所有通用逻辑集中维护
  • 子类只需关注自身特有的配置(路由、权限等)
  • 统一CRUD操作的日志、异常处理(可在基类中扩展)
  • 避免了路由构建器方案中访问内部受保护字段的问题,通过抽象属性传递配置参数

内容的提问来源于stack exchange,提问作者Zac Andersen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:15:58