2

3 つの基本クラスを処理する 3 つの一般的なリポジトリがあります。

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();
    }
}

基本クラスに応じて異なる方法でエンティティをフィルタリングする 1 つのリポジトリを持つ方法はありますか? 次のようなもの:

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();
    }
}

編集。質問は、エンティティが特定のタイプであるかどうかを確認する方法に関するものではありません。本当に難しいのは、削除済みまたはその他のプロパティでエンティティをフィルタリングできることがわかっている場合にフィルターを適用することです。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

あなたはそれを確認することができます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 に答える
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 に答える