2

次のクラスとインターフェイスで構成される基本的な設計があります。

  • IRepository<TEntity>インターフェース、
  • Repository<TEntity>基本クラス、
  • そして具体的なTenantRepositoryクラス。

問題"

インターフェイスによって継承されたものはすべて、定義によりパブリック アクセスを持っているため、Addメソッド (基本クラス)を呼び出すことができます。

_tenantRepository.Add(new Tenant { Name = "blah" } );

Createメソッドを呼び出す必要がある間TenantRepository

_tenantRepository.Create("blah");

質問

クライアントコードがメソッドにアクセスできないようにメソッドを保護されたものとして定義できればいいのですがAdd、それはインターフェイスで定義されたメソッドであり、パブリックアクセスが必要であるという単純な事実のために許可されていません。

あるいは、具象クラスの実装を実際にオーバーライドできるように、メソッドに同じ名前を付けることもできます。これにより、クライアント コードが を直接呼び出すことができなくなりますRepository.Add。しかし、場合によっては、クライアント コードが基本クラスで定義されたメソッドを呼び出さないようにしたいことがあります。

別の方法として、次のように書くこともできます。

    new protected void Add(Tenant tenant)
    {

    }

しかし、それは私を震えさせます(そして、メソッド名のリファクタリングを開始するとすぐに壊れます)。

これを達成するためのより良い方法はありますか?


参考としていくつかのコード スニペット:

インターフェース:

public interface IRepository<TEntity> : IDisposable where TEntity : IEntity
{
    IQueryable<TEntity> GetAll();
    void Delete(TEntity entity);
    void Add(TEntity entity);
}

基本クラスのごく一部:

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity
{
    protected IDbContext Context;

    public Repository(IDbContext context)
    {
        Context = context;
    }

    public void Add(TEntity entity)
    {
        DbSet.Add(entity);
    }

    // Left out other, for this question irrelevant, method implementations 
}

そして最後にTenantRepository

public class TenantRepository : Repository<Tenant>
{
    public TenantRepository(IDbContext context)
        : base(context)
    {
    }

    public Tenant Create(string tenantName)
    {
        var tenant = new Tenant
            {
                Name = tenantName,
                Guid = Guid.NewGuid().ToString()
            };

        if (Exists(tenant.Name))
        {
            throw new TenantAlreadyExistsException(tenant.Name);
        }

        Add(tenant);

        return tenant;
    }

    // Left out other, for this question irrelevant, method implementations 
}
4

3 に答える 3

1

1 つの解決策は、TenantRepository がリポジトリから継承されないようにすることです。結局のところ、それらには異なる機能があるように思えます (追加ではなく作成が必要です)。

このルートに進むと、Repository は TenenantRepository クラスのプライベート メンバーになります。

于 2013-02-24T13:59:12.650 に答える
1

明示的なインターフェイスの実装を使用して Add メソッドを非表示にすることができます。基本的に、リポジトリでこれを行います:

public IRepository<Tenant>.Add(Tenant toAdd)
{
    //do the add
}

これは、IRepository にキャストすることによってのみ取得できます。

于 2013-02-24T14:00:15.727 に答える
0

の一意性を確認TenantRepositoryする必要がある場合は、そのロジックをメソッド自体に含める必要があります。基本クラスとそれをTenantRepositoryで作成して、メソッドで現在使用している一意性チェックを実行する必要があります。AddTenantAddAddRepositoryvirtualoverrideCreate

public interface IRepository<T> 
{
    void Add(T entity);
}

public class Repository<T> : IRepository<T> 
{
    // mocking Add so it works without a DB
    public virtual void Add(T entity) 
    {
        Console.WriteLine("{0} added", entity.ToString());
    }
}

public class Tenant 
{
    public string Name{get; private set;}
    public Tenant(string Name)
    {
        this.Name=Name;
    }

    public override string ToString() {return this.Name;}

}

public class TenantRepository : Repository<Tenant>
{
    // Add is virtual, so it can be overridden by TenantRepository
    public override void Add(Tenant entity)
    {
        // this represents your uniqueness check
        if(entity.Name=="Paolo") throw new Exception();

        base.Add(entity); // calling Add on the base Repository
    }

    //you can now avoid having Create or making it just call Add
    public Tenant Create(Tenant entity) 
    {
        this.Add(entity);
        return entity;
    }
}
于 2013-02-24T15:25:29.740 に答える