C# 泛型 Class 与接口
C# Generics Class vs Interface
我有一个通用存储库,用于更新我的 EF 数据上下文,如下所示(为简洁起见缩短):
public interface IRepository<T> where T : class
{
void Add(T entity);
void Update(T entity);
void Delete(T entity);
IQueryable<T> Find(Expression<Func<T, bool>> filter = null);
}
public class Repository<TEntity, TContext> : IRepository<TEntity>
where TEntity : class
where TContext : DbContext
{
public IUnitOfWork UnitOfWork { get; set; }
public TContext DataContext { get; set; }
public Repository(IUnitOfWork unitOfWork, TContext dataContext)
{
UnitOfWork = unitOfWork;
DataContext = dataContext;
}
public virtual void Add(TEntity entity)
{
DataContext.Set<TEntity>().Add(entity);
}
public virtual void Update(TEntity entity)
{
DataContext.Set<TEntity>().Attach(entity);
DataContext.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete(TEntity entity)
{
if (DataContext.Entry(entity).State == EntityState.Detached)
DataContext.Set<TEntity>().Attach(entity);
DataContext.Set<TEntity>().Remove(entity);
}
public IQueryable<TEntity> Find(System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = null)
{
IQueryable<TEntity> query = DataContext.Set<TEntity>();
if (filter != null)
query = query.Where(filter);
return query;
}
}
我想创建一个 IArchiveOnlyRepository 以用于实现我的 IArchiveable 接口的实体。我希望这会起作用:
public interface IArchiveable
{
bool IsArchived { get; set; }
DateTime? ArchivedOn { get; set; }
string ArchivedBy { get; set; }
}
public interface IArchiveOnlyRepository<T> where T : IArchiveable
{
void Add(T entity);
void Update(T entity);
void Archive(T entity);
IQueryable<T> Find(Expression<Func<T, bool>> filter = null);
}
public class ArchiveOnlyRepository<TEntity, TContext> : IArchiveOnlyRepository<TEntity>
where TEntity : IArchiveable
where TContext : DbContext
{
public IUnitOfWork UnitOfWork { get; set; }
public TContext DataContext { get; set; }
public ArchiveOnlyRepository(IUnitOfWork unitOfWork, TContext dataContext)
{
UnitOfWork = unitOfWork;
DataContext = dataContext;
}
public virtual void Add(TEntity entity)
{
DataContext.Set<TEntity>().Add(entity);
}
public virtual void Update(TEntity entity)
{
DataContext.Set<TEntity>().Attach(entity);
DataContext.Entry(entity).State = EntityState.Modified;
}
public virtual void Archive(TEntity entity)
{
if (DataContext.Entry(entity).State == EntityState.Detached)
DataContext.Set<TEntity>().Attach(entity);
entity.IsArchived = true;
entity.ArchivedOn = DateTime.UtcNow;
entity.ArchivedBy = UnitOfWork.UserName;
}
public IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>)
{
IQueryable<TEntity> query = DataContext.Set<TEntity>();
if (filter != null)
query = query.Where(filter);
return query;
}
}
不幸的是,以下几行:
DataContext.Set<TEntity>()...
生成以下错误:
The Type 'TEntity' must be a reference type in order to use it as parameter 'TEntity'
我如何定义这个通用存储库以确保 T 是实现 IArchiveable 的 class?
您只需要将 class
类型约束放回:
where TEntity : class, IArchiveable
你只需要将TEntity
约束为class
(引用类型)
public interface IArchiveOnlyRepository<T> where T : IArchiveable, class
...
和
public class ArchiveOnlyRepository<TEntity, TContext> : IArchiveOnlyRepository<TEntity>
where TEntity : IArchiveable, class
where TContext : DbContext
....
改变一下
where TEntity : IArchiveable
至
where TEntity : class, IArchiveable
我有一个通用存储库,用于更新我的 EF 数据上下文,如下所示(为简洁起见缩短):
public interface IRepository<T> where T : class
{
void Add(T entity);
void Update(T entity);
void Delete(T entity);
IQueryable<T> Find(Expression<Func<T, bool>> filter = null);
}
public class Repository<TEntity, TContext> : IRepository<TEntity>
where TEntity : class
where TContext : DbContext
{
public IUnitOfWork UnitOfWork { get; set; }
public TContext DataContext { get; set; }
public Repository(IUnitOfWork unitOfWork, TContext dataContext)
{
UnitOfWork = unitOfWork;
DataContext = dataContext;
}
public virtual void Add(TEntity entity)
{
DataContext.Set<TEntity>().Add(entity);
}
public virtual void Update(TEntity entity)
{
DataContext.Set<TEntity>().Attach(entity);
DataContext.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete(TEntity entity)
{
if (DataContext.Entry(entity).State == EntityState.Detached)
DataContext.Set<TEntity>().Attach(entity);
DataContext.Set<TEntity>().Remove(entity);
}
public IQueryable<TEntity> Find(System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = null)
{
IQueryable<TEntity> query = DataContext.Set<TEntity>();
if (filter != null)
query = query.Where(filter);
return query;
}
}
我想创建一个 IArchiveOnlyRepository 以用于实现我的 IArchiveable 接口的实体。我希望这会起作用:
public interface IArchiveable
{
bool IsArchived { get; set; }
DateTime? ArchivedOn { get; set; }
string ArchivedBy { get; set; }
}
public interface IArchiveOnlyRepository<T> where T : IArchiveable
{
void Add(T entity);
void Update(T entity);
void Archive(T entity);
IQueryable<T> Find(Expression<Func<T, bool>> filter = null);
}
public class ArchiveOnlyRepository<TEntity, TContext> : IArchiveOnlyRepository<TEntity>
where TEntity : IArchiveable
where TContext : DbContext
{
public IUnitOfWork UnitOfWork { get; set; }
public TContext DataContext { get; set; }
public ArchiveOnlyRepository(IUnitOfWork unitOfWork, TContext dataContext)
{
UnitOfWork = unitOfWork;
DataContext = dataContext;
}
public virtual void Add(TEntity entity)
{
DataContext.Set<TEntity>().Add(entity);
}
public virtual void Update(TEntity entity)
{
DataContext.Set<TEntity>().Attach(entity);
DataContext.Entry(entity).State = EntityState.Modified;
}
public virtual void Archive(TEntity entity)
{
if (DataContext.Entry(entity).State == EntityState.Detached)
DataContext.Set<TEntity>().Attach(entity);
entity.IsArchived = true;
entity.ArchivedOn = DateTime.UtcNow;
entity.ArchivedBy = UnitOfWork.UserName;
}
public IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>)
{
IQueryable<TEntity> query = DataContext.Set<TEntity>();
if (filter != null)
query = query.Where(filter);
return query;
}
}
不幸的是,以下几行:
DataContext.Set<TEntity>()...
生成以下错误:
The Type 'TEntity' must be a reference type in order to use it as parameter 'TEntity'
我如何定义这个通用存储库以确保 T 是实现 IArchiveable 的 class?
您只需要将 class
类型约束放回:
where TEntity : class, IArchiveable
你只需要将TEntity
约束为class
(引用类型)
public interface IArchiveOnlyRepository<T> where T : IArchiveable, class
...
和
public class ArchiveOnlyRepository<TEntity, TContext> : IArchiveOnlyRepository<TEntity>
where TEntity : IArchiveable, class
where TContext : DbContext
....
改变一下
where TEntity : IArchiveable
至
where TEntity : class, IArchiveable