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

ASP.NET Core项目如何组织可最小化仓储、服务等模块的代码重复?

消除ASP.NET Core代码重复与大型项目组织方案

一、消除重复代码的具体方案

1. 仓储层:泛型仓储封装通用CRUD

定义通用仓储接口和基类,把重复的CRUD逻辑抽离出来,具体实体仓储仅需实现专属业务逻辑:

// 通用仓储接口
public interface IRepository<T> where T : class
{
    Task<T?> GetByIdAsync(int id);
    Task<IEnumerable<T>> GetAllAsync();
    Task AddAsync(T entity);
    Task UpdateAsync(T entity);
    Task DeleteAsync(int id);
    Task SaveChangesAsync();
}

// 通用仓储实现基类
public class BaseRepository<T> : IRepository<T> where T : class
{
    protected readonly DbContext _context;
    protected readonly DbSet<T> _dbSet;

    public BaseRepository(DbContext context)
    {
        _context = context;
        _dbSet = context.Set<T>();
    }

    public async Task<T?> GetByIdAsync(int id) => await _dbSet.FindAsync(id);
    public async Task<IEnumerable<T>> GetAllAsync() => await _dbSet.ToListAsync();
    public async Task AddAsync(T entity) => await _dbSet.AddAsync(entity);
    public void UpdateAsync(T entity) => _dbSet.Update(entity);
    public async Task DeleteAsync(int id)
    {
        var entity = await GetByIdAsync(id);
        if (entity != null) _dbSet.Remove(entity);
    }
    public async Task SaveChangesAsync() => await _context.SaveChangesAsync();
}

// 具体实体仓储,仅实现专属逻辑
public class UserRepository : BaseRepository<User>, IUserRepository
{
    public UserRepository(AppDbContext context) : base(context) { }

    // 用户专属查询:根据邮箱获取用户
    public async Task<User?> GetByEmailAsync(string email)
    {
        return await _dbSet.FirstOrDefaultAsync(u => u.Email == email);
    }
}

2. 服务层:抽象基类封装通用业务逻辑

用抽象基类封装通用的实体服务逻辑,具体服务继承后专注于业务特有逻辑:

public abstract class BaseService<T> where T : class
{
    protected readonly IRepository<T> _repository;

    public BaseService(IRepository<T> repository)
    {
        _repository = repository;
    }

    public async Task<T?> GetByIdAsync(int id) => await _repository.GetByIdAsync(id);
    public async Task<IEnumerable<T>> GetAllAsync() => await _repository.GetAllAsync();
    public async Task AddAsync(T entity)
    {
        // 通用新增前校验逻辑
        ValidateEntity(entity);
        await _repository.AddAsync(entity);
        await _repository.SaveChangesAsync();
    }

    // 留给子类重写的专属校验方法
    protected virtual void ValidateEntity(T entity) { }
}

public class UserService : BaseService<User>, IUserService
{
    public UserService(IUserRepository repository) : base(repository) { }

    // 重写校验逻辑,添加用户专属规则
    protected override void ValidateEntity(User entity)
    {
        if (string.IsNullOrWhiteSpace(entity.Email))
            throw new ArgumentException("邮箱不能为空");
    }

    // 用户专属业务:重置密码
    public async Task ResetPasswordAsync(int userId, string newPassword)
    {
        var user = await GetByIdAsync(userId);
        if (user == null) throw new KeyNotFoundException("用户不存在");
        user.PasswordHash = HashPassword(newPassword);
        _repository.UpdateAsync(user);
        await _repository.SaveChangesAsync();
    }
}

3. 用例层:通用用例模板+复杂用例单独实现

针对通用CRUD场景定义泛型用例类,复杂业务用例则单独编写,避免重复造轮子:

// 通用用例:根据ID获取实体
public class GetEntityByIdUseCase<T> where T : class
{
    private readonly IRepository<T> _repository;

    public GetEntityByIdUseCase(IRepository<T> repository)
    {
        _repository = repository;
    }

    public async Task<T?> Execute(int id) => await _repository.GetByIdAsync(id);
}

// 复杂业务用例:创建订单(关联用户与书籍)
public class CreateOrderUseCase
{
    private readonly IOrderRepository _orderRepo;
    private readonly IUserRepository _userRepo;
    private readonly IBookRepository _bookRepo;

    public CreateOrderUseCase(IOrderRepository orderRepo, IUserRepository userRepo, IBookRepository bookRepo)
    {
        _orderRepo = orderRepo;
        _userRepo = userRepo;
        _bookRepo = bookRepo;
    }

    public async Task<Order> Execute(int userId, int bookId, decimal amount)
    {
        var user = await _userRepo.GetByIdAsync(userId);
        var book = await _bookRepo.GetByIdAsync(bookId);
        if (user == null || book == null) throw new ArgumentException("用户或书籍不存在");

        var order = new Order
        {
            UserId = userId,
            BookId = bookId,
            Amount = amount,
            OrderDate = DateTime.Now
        };

        await _orderRepo.AddAsync(order);
        await _orderRepo.SaveChangesAsync();
        return order;
    }
}

4. 其他复用技巧

  • 对象映射:用AutoMapper定义通用映射规则,减少实体与DTO的重复转换代码
  • 扩展方法:将分页、排序等通用查询逻辑封装为IQueryable<T>的扩展方法
  • 验证逻辑:用FluentValidation抽象通用验证规则,避免重复编写校验代码

二、大型ASP.NET Core项目组织方式

1. 分层架构(清晰分离关注点)

按职责划分项目层,遵循依赖倒置原则:

  • 领域层:核心实体、领域服务、仓储接口,是业务核心,不依赖外部层
  • 基础设施层:仓储实现、EF Core配置、第三方服务集成,依赖领域层
  • 应用层:用例、应用服务、DTO,协调领域层与基础设施层,依赖领域层接口
  • 表现层:API控制器、前端资源,依赖应用层
  • 公共层:通用工具类、扩展方法、常量,供各层调用

2. 按业务模块拆分结构

在分层基础上,按业务模块拆分代码,便于团队并行开发:

YourProject/
├── Domain/
│   ├── User/
│   │   ├── User.cs
│   │   ├── IUserRepository.cs
│   │   └── UserDomainService.cs
│   ├── Book/
│   │   ├── Book.cs
│   │   └── IBookRepository.cs
│   └── Order/
│       ├── Order.cs
│       └── IOrderRepository.cs
├── Infrastructure/
│   ├── Data/
│   │   ├── AppDbContext.cs
│   │   └── Repositories/
│   │       ├── UserRepository.cs
│   │       ├── BookRepository.cs
│   │       └── OrderRepository.cs
│   └── ExternalServices/
│       └── EmailService.cs
├── Application/
│   ├── User/
│   │   ├── DTOs/
│   │   ├── UseCases/
│   │   └── UserService.cs
│   ├── Book/
│   │   ├── DTOs/
│   │   ├── UseCases/
│   │   └── BookService.cs
│   └── Order/
│       ├── DTOs/
│       ├── UseCases/
│       └── OrderService.cs
├── WebApi/
│   ├── Controllers/
│   │   ├── UserController.cs
│   │   ├── BookController.cs
│   │   └── OrderController.cs
│   └── Program.cs
└── Shared/
    ├── Extensions/
    ├── Validators/
    └── DTOs/

3. 模块化依赖注入

在Program.cs中按模块注册服务,保持配置清晰:

var builder = WebApplication.CreateBuilder(args);

// 注册数据访问服务
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddScoped<IBookRepository, BookRepository>();

// 注册应用层服务
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<CreateOrderUseCase>();

// 注册工具类服务
builder.Services.AddAutoMapper(typeof(Program));
builder.Services.AddFluentValidationAutoValidation();

4. 统一处理横切关注点

  • 日志:用Serilog/NLog实现统一日志,避免各层重复编写日志代码
  • 异常处理:自定义全局异常中间件,统一API异常返回格式
  • 缓存:封装缓存服务,复用缓存逻辑,减少重复操作

内容的提问来源于stack exchange,提问作者Ali-Muhammad Zakaryaev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 15:49:56