解决User类继承IdentityUser与Entity多基类冲突适配Repository约束
解决C#单继承下Repository泛型约束与IdentityUser冲突的方案
方案1:将Entity抽象类改为接口(推荐)
C#只支持单继承,但允许多接口实现,把Entity改成接口后,User可以同时继承IdentityUser<int>并实现该接口,完美适配Repository的约束。
修改Entity定义:
public interface IEntity { int Id { get; set; } }
调整Repository的泛型约束:
internal abstract class Repository<TDomain, TEntity> : IReadWriteRepository<TDomain> where TDomain : Model where TEntity : class, IEntity // 约束改为实现IEntity接口 { private readonly DbContext _context; private readonly IMapper _mapper; protected Repository(DbContext context, IMapper mapper) { _context = context; _mapper = mapper; } public IQueryable<TDomain> Get() { var entities = _context.Set<TEntity>(); return entities.Select(e => _mapper.ToDomain(e)); } }
修改User类:
public class User : IdentityUser<int>, IEntity { // IdentityUser<int>已经自带int类型的Id属性,不需要重复定义 // 这里可以添加你的自定义业务属性 }
方案2:使用结构类型约束(C# 8.0及以上版本)
如果不想改动原有的Entity抽象类,可以直接在Repository的泛型约束中要求TEntity必须拥有int类型的Id属性,利用C# 8.0的结构类型(鸭子类型)特性,不需要强制继承某个类或接口。
调整Repository的约束:
internal abstract class Repository<TDomain, TEntity> : IReadWriteRepository<TDomain> where TDomain : Model where TEntity : class, new(), { int Id { get; set; } } // 直接约束Id属性存在 { private readonly DbContext _context; private readonly IMapper _mapper; protected Repository(DbContext context, IMapper mapper) { _context = context; _mapper = mapper; } public IQueryable<TDomain> Get() { var entities = _context.Set<TEntity>(); return entities.Select(e => _mapper.ToDomain(e)); } }
User类无需任何修改,因为IdentityUser<int>本身就包含int Id属性:
public class User : IdentityUser<int> { // 自定义属性 }
方案3:让Entity继承IdentityUser(局限性较大)
如果你的项目所有实体都需要身份认证相关特性,可以让Entity直接继承IdentityUser<int>,然后User继承Entity。但这种方案只适合所有实体都是用户相关的场景,通用性差。
修改Entity定义:
public abstract class Entity : IdentityUser<int> { // 可添加所有实体通用的属性 }
User类:
public class User : Entity { // 自定义属性 }
此时Repository的原有约束不需要修改,因为TEntity继承Entity,自然满足要求。
内容的提问来源于stack exchange,提问作者KTOV
相关产品推荐
相关产品推荐

