我在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
}
答案 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;
}
}