在DDD中,viewmodel如何重用领域模型行为?

Ste*_*ios 2 c# wpf domain-driven-design behavior viewmodel

我不确定,但只要我读到有关 ddd 的内容,域模型就永远不应该离开应用程序层..如果这是真的,那么视图模型如何重用域模型的行为?

从 ddd 角度假设以下发票模型

  public class Invoice
{
    public int Id { get; set; }

    public int CustomerID { get; internal set; }

    public void ChangeCustomer(Customer customer)
    {
        if (customer.IsActive == false)
            throw new Exception("Inactive customers cannot be used");

        CustomerID = customer.Id;
        //other properties change also that need to be reflected to the user interface
    }
}
Run Code Online (Sandbox Code Playgroud)

现在让发票 ViewModel 尝试 #1。按照这个想法,我在重用域行为方面没有问题,但域层必须引用本例中的 UI 项目(WPF)。但在这里我担心我们不应该在应用程序层之外使用域层

 public class InvoiceVMOption1 : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyUI(string PropertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
    }
    Invoice underlinesource;

    public InvoiceVMOption1(Invoice underlinesource)
    {
        this.underlinesource = underlinesource;
    }

    public int InvoiceID { get => underlinesource.Id; }
    public int CustomerID
    {
        get => underlinesource.CustomerID;
        set
        {
            try
            {
                //This is a very simple example. in reality when changing customer other properties of the domain change also.
                var customer = new CustomerService().Get(value);
                underlinesource.ChangeCustomer(customer);
                NotifyUI(nameof(CustomerID));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                throw;
            }

        }
    }

}
Run Code Online (Sandbox Code Playgroud)

现在让我们拥有 Invoice ViewModel 选项 #2 按照这个想法,这意味着应用程序服务负责构建视图模型并将其提供给 UI,然后 UI 返回视图模型 > 转换为域 > 通过存储库更新

   /// <summary>
/// I like more this idea as it decouple viewmodel from domain layer
/// The problem here is how i can reuse the logic of changing the customer since domain model is not referenced
/// </summary>
public class InvoiceVMOption2 : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyUI(string PropertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
    }

    private int invoiceid;
    public int InvoiceID
    {
        get => invoiceid;
        set
        {
            invoiceid = value;
            NotifyUI(nameof(InvoiceID));
        }
    }

    private int customerid;
    public int CustomerID
    {
        get => customerid;
        set
        {
            //user select a customer from combobox binding with his id
            //here we need to let the user whenever  any of the validation that exists in domain model invoice will fail when changing customer.
            //nothing will save yet
            //after user finish this viewmodel will be sent to application layer(service) convert it to domain and update through repository
            //Problem is, how i can know if customer will fail to change without writing same code validation from domain?
            customerid = value;
            NotifyUI(nameof(customerid));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Sub*_*han 5

视图模型是一条单向街道。它只是为了从域表示构建适合 UI 的数据结构。

UI 上的每个更改最好建模为单独的命令(如果您使用的是 CQRS)或调用特定应用程序服务的不同 API(如果您使用的是核心 DDD)。

通过选择对每个更改进行建模,您可以在代码中更准确地表示域。如果您要返回对数据结构进行修改的相同视图模型,则隐藏了这些更改的意图。流程模式也更接近 CRUD,因为您只需将数据传输到后端进行持久化。