【问题标题】:Class derived from generic type for template some bunch of property从泛型类型派生的类模板一些属性
【发布时间】:2017-02-03 14:48:48
【问题描述】:

在我的项目中,我尝试从 DAO 中分离域模型,例如 https://vaughnvernon.co/?p=879 中的示例。我使用它的类,我的域对象的后端状态是内部的并且仅在存储库中使用。接下来我有我的域对象,我想通用一些使用它的逻辑。有一个代码:

public abstract class GenericEntity<T> where T : class
{
    protected readonly T _state;

    internal GenericEntity(T state)
    {
        _state = state;
    }

    internal T State
    {
        get
        {
            return _state;
        }
    }
}

我想从这个类派生,但我的域模型应该是公共的,我不能这样做,因为内部 DAOEntity。

public class DomainModel : GenericEntity<DAOEntity>
{

}

internal class DAOEntity
{

}

是不是有些绕来绕去的?或者我需要实现这个代码来管理我所有班级的状态。我不想做一些基本的 DAOEntity 原因然后我需要在所有域模型中强制转换它。

编辑: 也许你不明白我的问题。现在我的代码看起来像 Marcos Jonatan Suriani 在他的回答中展示的:

public class Product 
{
  public Product()
  {
    State = new ProductState();
  }

  internal Product(ProductState state)
  {
    State = state;
  }
}

public class ProductState
{

}

public class AgilePMContext : DbContext
{
  public DbSet<ProductState> Products { get; set; }
}

但是我正在寻找一些设计模式,我可以通过我的内部状态实现减少复制粘贴代码,所以我想使用这个解决方案,因为当我有很多域模型时,这是我需要重复的代码总而言之。

【问题讨论】:

  • 我没有看到关于 GenericEntity 的问题。只需将 DAOEntity 类公开...只要将 State 保持在内部,就不会泄露责任。
  • 这是一些解决方案,但是在您建议的这种方法中,库的用户可以查看状态是如何得到支持的,我想避免它。

标签: c# domain-driven-design


【解决方案1】:
public class DomainModel : GenericEntity<DAOEntity>
{

}

这是倒退的——您已经编写了一个依赖于数据模型的域模型。您希望这种依赖关系反过来:数据模型应该依赖于域模型。

从某种意义上说,Vaughn 告诉您的是领域模型为数据服务提供者定义了接口,而数据模型实现了这些提供者。

例如,考虑一个简化的银行模型

class DepositModel : BankingApi.Deposit {
    void depositFunds(Account account, Deposit deposit, Clock clock) {

        AccountId currentAccount = account.id();
        AccountId depositInto = deposit.accountId();

        assert depositInto.equals(currentAccount);

        Money amount = deposit.amount();
        account.deposit(amount);

        Time processedAt = clock.now();
        TransactionId transactionId = deposit.transactionId();

        account.updateTransactionHistory(transactionId, processedAt)
    }
}

请注意模型没有触及原始数据。所有的状态操作都被值类型隐藏了。

这意味着您的数据模型可以按照您喜欢的任何方式实现数据结构,并以任何满足规范的方式对其进行操作。

【讨论】:

  • 为什么继承自BankingApi.Deposit
  • Vernon 公开了这种技术(DAL 的接口),但选择放弃这种方法。请再仔细阅读文章。 OP 正在询问由状态对象部分支持的域对象。可能是倒退的,但考虑到将域与持久性使用 EF 分离是多么困难,我认为这是一种很好且简单的方法。
【解决方案2】:

这篇文章的解决方案略有不同。该模式的主要目的是关注域核心并避免变通方法,特别是在将域对象映射到关系(ORM,即 ie)时。

采用这种方法将帮助我们专注于真正的 最重要的是我们的核心领域及其无处不在的语言。

方法是通过提供状态对象来使域尽可能无处不在——这将被 ORM (EF) 使用。因此,业务规则保留在 Domain 对象上,而 ORM 相关转到 State 对象。

一种方法使用带有实现类的分离接口,另一种方法使用由状态对象支持的域对象。

你的实现应该由代表领域的接口组成(例如IProduct):

我们创建了一个希望客户看到的接口,并将实现细节隐藏在实现类中。

并且还由两个实现的接口组成;一个用于域对象 (Product),另一个用于状态对象 (ProductState)。域实现应该有两个构造函数:

普通客户端的公共业务构造函数和仅由内部实现组件使用的第二个内部构造函数。

interface IProduct
{
}

public class Product : IProduct
{
  public Product()
  {
    State = new ProductState();
  }

  internal Product(ProductState state)
  {
    State = state;
  }
}

public class ProductState: IProduct
{

}

public class AgilePMContext : DbContext
{
  public DbSet<ProductState> Products { get; set; }
}

【讨论】:

  • 我这样做是对的。但我想用获取状态模型和构造函数的内部方法通用复制粘贴代码。
猜你喜欢
  • 2015-01-26
  • 1970-01-01
  • 2014-03-22
  • 2011-10-09
  • 2011-05-24
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 2012-09-08
相关资源
最近更新 更多