2011-11-15 60 views
7

我想知道什麼是設計DTO對象的構造函數的最佳做法。C#Dto構造函數和依賴注入

說,我有一個DTO對象是這樣的:

class CustomerDto 
{ 
    public string Name { get; set; } 
    public string Surname { get; set; } 
    public string Phone { get; set; } 
    ... 
} 

有幾種方法來構造對象:當你看到這

public CustomerDto(string name, string surname, string phone, ...) 
{ 
    this.Name = name; 
    this.Surname = surname; 
    this.Phone = phone; 
    ... 
} 

我可以聲明構造構造函數並立即結束SRP(單個責任)違規?

即使這些屬性都是相關的。

人們也可能會認爲沒有必要驗證屬性,因爲這是一個DTO並且沒有任何行爲,行爲應該位於此映射的域對象上。

在C#中,我們還可以更優雅的構造這個對象:

var dto = new CustomerDto() 
{ 
    Name = "Some name", 
    Surname = "Some surname" 
} 

或者用一口流利的建設者或如NBuilder的框架。

Automapper也有自動映射框架的用法。問題還在於使用Ioc容器,Ctor變得複雜,以及交換參數的風險,例如,如果您姓氏在哪裏傳遞,反之亦然,驗證可能會錯過這個更容易,然後顯式映射,如上所述。

請幫助說服我哪一種更好的方法。

+0

[依賴注入 - 使用數據傳輸對象(DTO)?](http:// stackoverflow。com/questions/6297322/dependency-injection-use-with-data-transfer-objects-dtos) –

+0

我遇到了同樣的問題,並決定不使用構造函數。出於一個簡單的原因:稍後,在一個月或6幾個月,我或其他人會看這個,並且必須以我自己(和你自己)現在所想的方式思考它。我發現在閱讀代碼的過程中思考它太複雜了。 – dferraro

回答

10

您的示例中的值類型不是依賴關係。依賴性爲消費者提供功能(或配置)。在你的情況下,它們只是分配給你的DTO的正常值。只要數據屬於一起,即使在構造函數中分配了很多值,也不會違反SRP。這種情況下的唯一責任是保存數據。

另外DTO不應該由IoC容器創建,並且沒有真正的依賴關係。您應該通過持久性框架或使用自動映射手動創建它們。

如果使用構造函數或屬性分配值更好取決於使用情況。如果他們是必需的構造函數變種更好。如果他們是可選的財產方式更好。

+0

我喜歡這個答案,它確認了我對依賴關係的看法,而且這些並不是真正的依賴關係,它們不是您想讓Ioc容器替代的外部子系統。另外,選項2的原因是它確實允許自動映射框架完成它的任務,它只是在邊界之間傳輸數據。我確實認爲dto需要說出一個名稱的爭論並不是它真正關心的問題?同意? – Andre

3

我建議使用不可變數據結構,以便DTO實體不會公開任何setter,顯然這樣構造函數應該提供初始化給定DTO的所有基礎屬性的能力。

所以我更喜歡:

public CustomerDto(string name, string surname, string phone, ...) 

DTO是數據傳輸對象,尤其是代表一組屬性跨系統(分佈式以及)邊界傳遞,所以不要打擾太多關於SRP違反。 這就像Facade的設計模式,它突破了一組操作/服務以簡化使用。所以在這個kase Keep It Simple贏了。

+1

我想知道的是Martin fowler將數據傳輸對象描述爲一個保存狀態並且沒有行爲的對象,並且實際上將它描述爲一種減少方法調用的方法。通過引入構造函數參數並驗證它們,您就添加了行爲。請記住,目的是從域映射到視圖,並且最有可能在域對象上進行驗證。那麼dto是否真的需要擔心這些爭論以及需要什麼,因爲它只是將數據攜帶到其他地方,而驗證則是另一個問題? – Andre

+1

像'not null' /'not empty'這樣的參數驗證不是一個對象行爲,認爲它就像你的應用程序框架服務的東西。但是如果你打算像'if(customerRole == Roles.Vip)IncreaseBonus(x)'那樣封裝驗證 - 這將是行爲的確並且不應該在DTO本身中,DTO代表對象的最終satte – sll

+0

我剛剛測試過它看起來像Automapper是非常聰明的,它會將構造函數參數映射到屬性。事情是,雖然我認爲它取決於用法,如果你從一個域對象(已驗證)映射到一個視圖(驗證)沒有理由創建構造函數參數,它看起來像構造函數的方法沒有缺點,但我可以看到一個大的。你不能立即發現一個論點是否是錯誤的方法,或者實際上是一個論點映射到的屬性? – Andre