域实体的继承/设计问题可以是单个的或组合的

时间:2009-09-29 16:12:23

标签: .net repository-pattern data-access-layer multiple-inheritance

我完全混淆了自己试图设计必要的接口和摘要来完成域实体的加载,这些域实体可以单独使用,也可以组合成聚合。哇。那是一句流行语。本质上,我有两个对象,我希望有基本类型“加载”功能,但当这两个对象合并为一个时,我会遇到多重继承。

所以,我有我的实体,就像这样(我画了

public class Account
public class Document
public class AccountDocument
{
    public Account Account{get;set;}
    public Document Document{get;set;}
}

然后,我有接口,像这样:

public interface IAccountRepository
{
    Account Load(IDataContext context);
}

public interface IDocumentRepository
{
    Document Load(IDataContext context);
}

public interface IAccountDocumentRepository
{
    AccountDocument Load(IDataContext context);
}

由于Account和Document都可以(并且是)从其他实体派生,我想在实现中提供基本功能,以便我遵循DRY。

public abstract class AccountRepositoryBase : IAccountRepository
{
    Account Load(IDataContext context)
    {
        //implementation for loading the Account from the context
    }
}

public abstract class DocumentRepositoryBase : IDocumentRepository
{
    Document Load(IDataContext context)
    {
        //implementation for loading the Document from the context
    }
}

这适用于个人帐户和文档对象及其派生,但我似乎无法解决的问题是如何处理AccountDocument ......

public class AccountDocumentRepository : AccountRepositoryBase, DocumentRepositoryBase
{
    //This is not possible, of course, due to multiple inheritance.
}

我知道解决方案不会那么难,但我完全纠缠不清,无法理解如何只提供一次基本“加载”功能。请帮忙!

提前致谢。

3 个答案:

答案 0 :(得分:2)

您可以使用组合而不是实现继承来解决这个问题 - 只需让AccountDocumentRepository委托给您已编写的存储库类:

public class AccountDocumentRepository : IAccountDocumentRepository
{
    IAccountRepository accountRepository = new AccountRepositoryBase();
    IDocumentRepository documentRepository  = new DocumentRepositoryBase();

    public AccountDocument Load(IDataContext context) {
        Document document = this.documentRepository.Load(context);
        Account  account  = this.accountRepository.Load(context);
        return new AccountDocument(account, document);
    }
}

如果您希望灵活地替换不同的具体存储库,则可以提供一个或多个构造函数,以便客户端代码注入IAccountRepositoryIDocumentRepository

有几个很好的StackOverflow问题讨论了实现继承和组合的相对优点,并解释了为什么我们应该更喜欢组合。这些只是搜索“作品继承”的一小部分结果。

答案 1 :(得分:1)

您不希望AccountDocumentRepository实施IAccountDocumentRepository,而不是继承AccountRepositoryBaseDocumentRepositoryBase吗?

然后,您始终可以将AccountRepositoryBaseDocumentRepositoryBase属性添加到IAccountDocumentRepository界面,或将它们添加到AccountDocumentRepository的构造函数中,以确保您拥有两者的实例工作。

public class AccountDocumentRepository : IAccountDocumentRepository
{
    public AccountDocumentRepository(AccountRepositoryBase account, DocumentRepositoryBase document)
    {
        this.account = account;
        this.document = document;
    }

    public AccountDocument Load(IDataContext context)
    {
        //use your account & document instances here to create an AccountDocument.
    }

}

答案 2 :(得分:0)

您可能希望从“企业应用程序架构模式”一书中查看继承映射器模式

然后基于它创建自己的继承存储库模式。

请参阅:

  • 单表继承(278),
  • 类表继承(285),
  • 具体表继承(293),
  • 继承映射器(302)。

http://martinfowler.com/eaaCatalog/