2

我有三个处理三个基类的通用存储库:

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 属性。

4

5 回答 5

3

你可以通过强制转换来做到这一点,但我会质疑只执行非泛型功能的泛型方法的有用性。

我的意思是,如果没有针对一种以上类型执行的通用代码,那么在我看来,您实际上也可以在特定于类的派生中实现它。

于 2012-12-10T13:36:29.930 回答
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;
    }
}

使用这种方法,您可以减少重复代码的数量,但增加代码库的可读性和可维护性。

于 2012-12-10T13:47:04.027 回答
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...
于 2012-12-10T13:36:21.500 回答
0

您可以通过以下方式检查is

if (TEntity is LogicalStorageEntity)
    ...
if (TEntity is ArchiveEntity)
    ...
于 2012-12-10T13:38:52.487 回答
0

我会使用isover 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();
        }
于 2012-12-10T13:39:13.000 回答