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

发布于 2024-08-05 22:56:45 字数 1408 浏览 3 评论 0原文

我完全困惑于尝试设计必要的接口和抽象来完成域实体的加载,这些域实体可以由它们自己使用,也可以组合成一个聚合。哇。那是一个满口的流行语。本质上,我有两个对象,我希望它们具有基类型“加载”功能,但是当这两个对象合并为一个时,我遇到了多重继承。

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

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 对象及其派生来说

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.
}

我知道解决方案不能很难,但我完全困惑,无法理清如何仅提供一次基本“加载”功能。请

提前致谢!

I have completely confused myself trying to design the necessary interfaces and abstracts to accomplish loading of domain entities that can be used by themselves as well as combined into an aggregate. Wow. That was a buzzword mouthful. Essentially, I have two objects that I would like to have base-type "load" functionality, but when these two objects are combined into one, I run into multiple inheritance.

So, I have my entities, which are like this (I'd draw

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

Then, I have interfaces, like this:

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

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

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

Since both Account and Document can (and are) being derived from for other entities, I want to provide base functionality in the implementation so that I follow 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
    }
}

This works fine for the individual Account and Document objects and their derivations, but the problem I can't seem to wrap my head around is how to handle the AccountDocument...

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

I know the solution can't be that hard, but I am completely tangled up and can't straighten out how I can provide the base "Load" functionality only once. Please help!

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

溺深海 2024-08-12 22:56:45

您可以通过使用组合而不是实现继承来解决此问题 - 只需让 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 有几个很棒的问题讨论了实现继承和组合的相对优点,并解释了为什么我们应该强烈推荐组合。这些只是搜索“组合继承”的一小部分结果。

You can solve this by using composition instead of implementation inheritance - just let AccountDocumentRepository delegate to the the repository classes you've already written:

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

If you want the flexibility to substitute different concrete repositories, you can provide a constructor or properties that lets client code inject the IAccountRepository and IDocumentRepository.

There are several great StackOverflow questions that discuss the relative merits of implementation inheritance and composition and explain why we should strongly prefer composition. These are just a small selection of results from searching on "composition inheritance".

゛清羽墨安 2024-08-12 22:56:45

您是否不想让 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.
    }

}

Wouldn't you want AccountDocumentRepository to implement IAccountDocumentRepository, and not inherit from AccountRepositoryBase and DocumentRepositoryBase?

Then you can always add AccountRepositoryBase and DocumentRepositoryBase properties to the IAccountDocumentRepository interface, or add them to the constructor of AccountDocumentRepository to ensure you have instances of both to do the work.

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.
    }

}
趴在窗边数星星i 2024-08-12 22:56:45

您可能想查看《企业应用程序架构模式》一书中的继承映射器模式

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

请参阅:

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

http://martinfowler.com/eaaCatalog/

You might want to look into the Inheritance Mapper Pattern from the Patterns Of Enterprise Application Architecture book.

and then make your own kind of Inheritance Repository Pattern based on it.

See:

  • Single Table Inheritance (278),
  • Class Table Inheritance (285),
  • Concrete Table Inheritance (293),
  • Inheritance Mappers (302).

http://martinfowler.com/eaaCatalog/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文