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

一种解决方案是使 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

如果在 a 中TenantRepository您需要Add检查 的唯一性Tenant,则应将该逻辑包含在Add方法本身中。您应该Add在您的基RepositoryvirtualoverrideTenantRepository 中进行创建,以便它执行您现在在Create方法中进行的唯一性检查。

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 回答