实例化业务实体而不会丢失封装

时间:2013-07-12 03:03:43

标签: c# design-patterns domain-driven-design

我在Customer项目中有一个Domain业务实体,我希望根据其属性在DomainService项目中实例化它。有一些业务逻辑在创建时需要强制执行,例如, Salary取决于FirstName(仅限示例)。我不希望它的公司因公开而失去封装。

如何在不丢失封装的情况下实例化/初始化它。可以更改setter的私有,而不是公开。

 public class Customer
    {
        public int Id { get; private set; }

        public string Firstname { get; private set; }

        public string Surname { get; private set; }

        public decimal Salary { get; private set; }
        //... other properties
    }

3 个答案:

答案 0 :(得分:3)

如果你的要求是严格的封装..那么你唯一真正的选择(我现在能想到的)是使用构造函数:

public Customer(string firstName, string surname, decimal salary, ...)

允许直接操作这样的域对象并不是罪过。如果您担心会发生什么......要么给他们支持字段,要么让您的实体公开一个公共接口来对它们进行更改(可能使用某种Guard类来确定有效性。) / p>

答案 1 :(得分:1)

通常,您将创建一个Customer实例的两种方案。

答:从存储库中检索现有的客户。在这种情况下,在将客户存储到存储库之前考虑验证约束时,您不需要强制执行约束。

B:全新的客户。如果存在一些重要的域约束,您可以使用工厂来封装创建。

答案 2 :(得分:0)

如果您的验证可以在Customer级别上运行,建议您添加一个属性,例如IsValid,它会在Customer对象上运行业务规则。几个实现可以如下:

public bool IsValid
{
    get
    {
        return !string.IsNullOrWhiteSpace(Firstname) && Salary > 0;
    }
}

public Dictionary<string, string> IsValid2
{
    get
    {
        var errors = new Dictionary<string, string>(); //TODO: Instantiate only if errors are found

        if (string.IsNullOrWhiteSpace(Firstname))
        {
            errors.Add("ERR_001", "First name is invalid.");
        }

        if (Salary <= 0)
        {
            errors.Add("ERR_002", "Salary should be a positive number.");
        }

        return errors;
    }
}