NHibernate - 使用抽象基础来提供功能而不是接口是否可以?

时间:2009-03-24 02:23:53

标签: nhibernate inheritance interface

我对NHibernate相当新,并且在我的存储库类中遇到了一个奇怪的继承链问题。我一直在使用Gabriel Schenker's FAQ作为参考,并且按照他的示例,我一直在创建接口来定义“存储库”类中DAO操作的合同。我正在使用的数据模式相当广泛,过了一会儿我发现自己复制了很多代码。具体来说,在向基本接口添加通用“EntityType”参数后,Add,Update,Delete和“GetByID”方法完全相同。因此,例如,这将是存储库操作的最基本接口:

public interface IBasicRepository<EntityType> where EntityType : class
{
    void Add(EntityType entity);
    void Remove(EntityType entity);
    void Update(EntityType entity);
    EntityType GetByID<IDType>(IDType id);
}

为了简洁起见,我将从现在开始讨论Add方法。使用通用EntityType,实现完全相同:

public void Add(EntityType entity)
{
    using (ISession session = NHUtility.OpenSession())
    {
         using (ITransaction transaction = session.BeginTransaction())
         {
             session.Save(entity);
             transaction.Commit();
         }
    }
}

显然,反复键入相同的方法体(稍微改变类型)不仅令人讨厌,而且在我的书中设计不好。所以我创建了一个抽象基类,我将其称为RepositoryBase,它为Add()提供了实现。因为我使用的是抽象而不是接口,所以我为继承自RepositoryBase的类“打破了接口链”,并且我也被迫做出任何派生抽象,即使使用接口看起来更“正确”。使用这个糟糕的小实体示例....

public class Entity1
{
    public Guid ID { get; set; }
    public String Name { get; set; }
}

......一个人不能这样做......

public interface IEntity1Repository : RepositoryBase<Entity1>
{
    //Illegal!!!!  Bad, naughty programmer!
}

......但这很好......

public abstract class Entity1RepositoryBase : RepositoryBase<Entity1>
{
    public abstract ICollection<Entity1> GetByName(string name);
}

这只是困扰我。它工作正常,但它以错误的方式让我感到困惑,特别是因为使用这个特定模式的继承/实现链可能会非常深入。所以我想我的问题是:

  1. 我只是对此愚蠢和肛门保持?
  2. 我应该在这里看一下不同/更好的设计吗?我已经看了一些其他的例子(特别是Billy McCafferty's),Schenker的方法似乎对新手NHibernating来说最简单。
  3. 提前致谢。

1 个答案:

答案 0 :(得分:7)

一个选项可能是:

public interface IRepository<T> where T: class
{
    void Add(T entity);
    void Remove(T entity);
    void Update(T entity);
    T GetByID<IDType>(IDType id);
}

使用实现该接口的基类。即:

public abstract class RepositoryBase<T> : IRepository<T> where T: class
{
    ...
}

如有必要,将为每种类型的实体进行扩展:

public interface IProductRepository :  IRepository<Product>
{
    // Add extra methods
}

public class ProductRepository : RepositoryBase<Product>, IProductRepository 
{
    // Implement extra methods
}