2011-09-26 67 views
4

這個問題在過去的幾周或幾個月裏一直是我的頭腦,我真的不知道什麼是最好的解決方案。是否將我的DTO暴露給認爲不正確的視圖?

隨着我們使用視圖模型來公開數據視圖的MVVM圖案。例如,如果我想向用戶展示產品的詳細信息,我將在視圖模型中創建特定的屬性並填充它們。然後通過綁定,視圖將能夠從這些屬性獲取數據。像這樣:

<StackPanel> 
    <TextBlock Text="Prodcut Name:" FontWeight="Bold" /> 
    <TextBlock Text="{Binding Path=ProductName}" /> 

    <TextBlock Text="Price:" FontWeight="Bold"/> 
    <TextBlock Text="{Binding Path=Price}"/> 

    <TextBlock Text="Added Date:" FontWeight="Bold" /> 
    <TextBlock Text="{Binding Path=Date}"/> 
</StackPanel> 

在視圖模型中,我將檢索我想要顯示的數據。我將得到像產品DTO這樣的數據,這將在視圖中具有所需的屬性。

this.productDTO = getData(); 

所以我的問題是,我們可以直接從視圖模型綁定到dto嗎? 視圖模型:

private ProductDTO product; 

    public string ProductName 
    { 
     get { return this.product.Name; } 
     set { this.product.Name = value; } 
    } 

    public string Price 
    { 
     get { return this.product.Price; } 
     set { this.product.Price = value; } 
    } 

我的想法,露出DTO是不是一件好事.. 但如果它會救我脫離不必從DTO的所有屬性映射到視圖模型..

+0

我認爲在MVVM和View設計的模型之間插入代碼的最好方法是使用T4模板自動生成自定義類型描述符。 [這是一個很好的出發點](http://www.scottlogic.co.uk/blog/colin/2009/08/declarative-dependency-property-definition-with-t4-dte/),它描述瞭如何輕鬆創建依賴屬性。我重新編寫了它來創建自定義類型描述符,這些描述符並不難編碼。 VS2011在編譯器中有一些超級甜美的東西,使其更加簡單;看看Anders在Build上給出的演講,瞭解更多信息。 – Will

回答

5

如果您不需要「塑造」您的DTO以綁定您的視圖,那麼將DTO直接暴露給您的視圖絕對沒有錯。如果需要,您可以在將來的某個時間點引入視圖模型。

您還可以使用類似mini-ViewModel(其中I describe on my blog)的圖案添加本地化視圖模型以塑造模型的某些部分。

包裝一下你的DTO作爲你做一個視圖模型,添加代碼,不提供任何好處。它增加了代碼庫的大小和bug的風險。

KISS - 保持簡單!

+0

雖然我同意,但你應該記住,它被認爲是不好的OOP,以暴露數據對象的視圖,因爲你在那種方式,可能暴露*更多的屬性超過必要*。 –

5
private ProductDTO product; 

public string ProductName 
{ 
    get { return this.product.Name; } 
    set { this.product.Name = value; } 
} 

我可以看到的唯一問題是,當你的dto的Name屬性改變了它,而不是簡單地反映在你的UI中。所以我寧願這樣:

public ProductDTO Product {...} 

<TextBlock Text="{Binding Path=Product.Name}" /> 

當然,這需要你的DTO執行INotifyPropertyChanged

+1

+1用於意識到INPC的問題。通常數據實體不會實現INPC,所以有必要將其包裝在視圖模型中。 –

+0

但如果我這樣做,整個DTO將會暴露在視圖中。如果我們創建一個視圖將文本框綁定到我們不想更改的屬性(即產品的ID)。用戶可以改變我們的DTO。如果我們之後正在進行保存操作,這可能是非常危險的 –

2

技術上兩種方式都是可能的,但是一個DTO通常並不意味着觀看,因此可能不會觸發任何變更通知事件。您必須將其編碼到您的DTO中,否則就有可能導致UI同步問題。我建議不要以這種方式「豐富」你的DTO。

從架構的觀點來看DTO對象應該是廉價和小物體。他們不需要很多努力來實例化或銷燬,而且你不應該將它們傳遞給你的調用堆棧,更不要說讓它們留在內存中很長時間。一般來說,它們意味着數據膠囊,它們的目的僅僅是將數據從A帶到B.另一方面,ViewModel具有行爲並實現更豐富的接口。他們唯一與DTO有共同之處就是他們也有數據屬性。

所以,你的情況我建議不要保持DTO在您的視圖模型作爲一個私有成員,但在檢索到DTO設置視圖模型屬性,然後又忘記了DTO。作爲一般建議,不要讓DTO的壽命超過服務調用的方法。

+0

我正在做那件事,你現在正在建議。但它是一種討厭..當我得到的數據,我必須映射到視圖模型。而當我想保存它時則相反。我覺得我正在寫代碼,而且很容易忘記映射其中一個屬性。 –

+0

如果您想節省繁瑣的編碼任務,您可以查看域驅動設計並編寫一個模型,以便您自動生成大量代碼。例如,我將Entity Framework edmx模型作爲我的領域模型,並編寫了幾個T4模板,這些模板將爲我生成大量代碼:DTO,實體和DTO之間的映射,客戶端業務對象,它們的接口和映射DTO和業務對象之間。我從[Samuel Meacham]得到了這個想法(http://samscode.com/index.php/2010/06/entity-framework-v4-end-to-end-application-strategy-part-1-intro/)。 – Andreas