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

如何为两个独立领域创建Generic Repository避免新增额外依赖?

方案1:调整通用仓储设计,移除对统一基类的硬依赖

这是完全符合要求的最优解,不需要领域项目引入任何外部依赖,也不需要创建公共基础项目:
你可以把通用仓储对BaseEntity的继承约束,替换为初始化时传入Id属性的访问委托,示例代码如下:

public class GenericRepository<T>
{
    private readonly Func<T, int> _getIdSelector;

    // 构造函数接收对应实体的Id获取逻辑
    public GenericRepository(Func<T, int> getIdSelector)
    {
        _getIdSelector = getIdSelector;
    }

    public T SomeActionThatRequiresId(int id)
    {
        // 此处直接通过委托获取实体Id,不需要T继承任何基类或接口
    }
}

使用时你只需要在两个独立的DataAccess项目中,为各自的实体初始化仓储时传入对应Id的选择器即可,比如:

// 领域1的仓储初始化
var orderRepository = new GenericRepository<Order>(o => o.Id);
// 领域2的仓储初始化
var customerRepository = new GenericRepository<Customer>(c => c.Id);

这个方案完全满足DRY原则,仓储的核心逻辑只需要实现一次,两个DataAccess项目都可以复用,同时领域项目不需要做任何修改,也不需要引入任何外部依赖。


方案2:使用接口约束+源生成器自动适配

如果你更倾向于用类型约束来做编译级检查,不想传委托,可以选择这个方案:

  1. 在通用仓储项目中定义一个只有Id属性的接口 IHasId,作为泛型约束:
public interface IHasId
{
    int Id { get; }
}

public class GenericRepository<T> where T : IHasId
{
    public T SomeActionThatRequiresId(int id)
    {
        // 直接通过IHasId.Id访问属性
    }
}
  1. 写一个极简单的源生成器,扫描两个领域项目中的实体,只要实体有Id属性,自动给它加上IHasId接口的实现,不需要修改领域项目的代码,也不需要领域项目引用仓储项目。

这个方案可以保留类型安全的编译检查,同时也不会破坏领域项目无外部依赖的规范。


临时备选方案

如果你的项目规模很小,也可以选择把同样的BaseEntity类分别复制到两个领域项目中,统一命名空间即可。不过这种方案违反DRY原则,后续修改需要同步两处,仅适合临时使用。

内容的提问来源于stack exchange,提问作者Adam Kaczmarski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 08:54:04