2013-07-12 52 views
0

我有一個Customer業務實體在Domain項目中,我想根據它的屬性在DomainService項目中實例化它。業務邏輯在創建時需要執行,例如, Salary取決於FirstName(僅限示例)。我不希望它的制定者公開丟失封裝。實例化業務實體不失封裝

如何實例化/初始化它而不會丟失封裝。二傳手的私人可以改變,而不是公開的。

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

您可能會發現在設計實體有趣的這篇博客文章:http://www.jefclaes.be/2013/04/designing-entities-immutability-first.html – JefClaes

回答

3

如果你的要求是嚴格的封裝..那麼你唯一的選擇(即我能想到的現在)使用的構造函數:

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

它不是一種罪過允許直接操作這樣的域對象。如果你擔心會發生什麼......或者給他們支持領域或讓你的實體公開一個公共接口來改變他們(這可能使用某種類型的Guard類來確定有效性)。

+0

的ctor是保護不變量的最佳地點。 – JefClaes

+0

我打包DateTime.Now,我需要使用DateTimeWrapper驗證Customer實體內的DateOfBirth,但我不能使用依賴注入,因爲構造函數就像上面那樣。任何想法? – Pingpong

1

通常,您將創建一個Customer實例。

A:正在檢索客戶存儲庫。在這種情況下,當客戶存儲到存儲庫之前,您不需要強制執行約束條件。

B:全新的客戶。如果存在一些重要的域約束,則可以使用工廠來封裝創建。

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