我有三个处理三个基类的通用存储库:
public class Entity
{
public int Id { get; set; }
}
public class Repository
{
public TEntity[] GetAll<TEntity>() where TEntity : Entity
{
return _context.Set<TEntity>.ToArray();
}
}
public class ArchiveEntity : Entity
{
public bool Deleted { get; set; }
}
public class ArchiveRepository
{
public TEntity[] GetAll<TEntity>() where TEntity : ArchiveEntity
{
return _context.Set<TEntity>.Where(x => x.Deleted == false).ToArray();
}
}
public class LogicalStorageEntity : ArchiveEntity
{
public int StorageId { get; set; }
}
public class LogicalStorageRepository
{
public int CurrentStorageId { get; set; }
public TEntity[] GetAll<TEntity>() where TEntity : LogicalStorageEntity
{
return _context.Set<TEntity>
.Where(x => x.Deleted == false)
.Where(x => x.StorageId = CurrentStorageId)
.ToArray();
}
}
是否有办法让一个存储库根据基类以不同方式过滤实体?看起来像:
public class Entity
{
public int Id { get; set; }
}
public class ArchiveEntity : Entity
{
public bool Deleted { get; set; }
}
public class LogicalStorageEntity : ArchiveEntity
{
public int StorageId { get; set; }
}
public class UniversalRepository
{
public TEntity[] GetAll<TEntity>() where TEntity : Entity
{
if (typeof(TEntity) is LogicalStorageEntity)
{
return _context.Set<TEntity>
.Where(x => /* how to filter by x.Deleted */)
.Where(x => /* how to filter by x.StorageId */)
.ToArray();
}
if (typeof(TEntity) is ArchiveEntity)
{
return _context.Set<TEntity>
.Where(x => /* how to filter by x.Deleted */)
.ToArray();
}
return _context.Set<TEntity>.ToArray();
}
}
编辑。静默不是关于如何检查实体是否属于特定类型。当您知道可以通过Deleted或其他属性过滤实体时,真正困难的部分是应用过滤器。由于存在TEntity:Entity限制,因此无法访问Deleted属性。
答案 0 :(得分:3)
你可以通过强制转换来实现,但我会质疑只执行非泛型功能的泛型方法的用处。
我的意思是,如果没有针对多种类型执行的公共代码,那么在我看来,您可能也会在类特定的派生中实现它。
答案 1 :(得分:2)
你可以,但你不应该。
每个实体类型的单独存储库是正确的方法,因为这样可以将实体特定逻辑封装在该实体的存储库中。如果您尝试创建一个通用存储库,则必须通过大量if
检查以大量方法添加/更改逻辑。
如果您想尝试促进一些代码重用,您可以从基本存储库提供功能,并允许特定存储库指定行为:
public abstract class Repository<TEntity> where TEntity : Entity
{
protected virtual Expression<Func<TEntity, bool>> Filter { get { return null; } }
public TEntity[] GetAll()
{
if (this.Filter == null)
{
return _context.Set<TEntity>().ToArray();
}
else
{
return _context.Set<TEntity>().Where(this.Filter).ToArray();
}
}
}
public class ArchiveRepository : Repository<Archive>
{
public ArchiveRepository()
{
this.Filter = archive => !archive.IsDeleted;
}
}
使用这种方法,您可以减少重复代码的数量,但可以提高代码库的可读性和可维护性。
答案 2 :(得分:0)
使用'as'投射。
LogicalStorageEntity lse = entity as LocalStorageEntity;
if (lse != null)
{
// we know that the entity is a LogicalStorageEntity
}
ArchiveEntity ae = entity as ArchiveEntity;
if (ae != null)
{
// we know that the entity is an ArchiveEntity
}
// etc...
答案 3 :(得分:0)
您可以使用is
:
if (TEntity is LogicalStorageEntity)
...
if (TEntity is ArchiveEntity)
...
答案 4 :(得分:0)
我使用is
而不是as
,但这无所谓。
if (TEntity is LogicalStorageEntity)
{
return _context.Set<TEntity>
.Where(x => /* filter by x.Deleted */)
.Where(x => /* filter by x.StorageId */)
.ToArray();
}
if (TEntity is ArchiveEntity)
{
return _context.Set<TEntity>
.Where(x => /* filter by x.Deleted */)
.ToArray();
}