2010-01-07 70 views
5

目前,我得到了相當不好的視圖模型。如何處理具有多個聚合根的視圖模型?

類看起來像這樣=>

public class AccountActionsForm 
    { 
     public Reader Reader { get; set; } 
     //something... 
    } 

問題是,閱讀器類型來自域模型(違反SRP的)。基本上,我正在尋找設計技巧(即將視圖模型分解爲輸入/輸出是一個好主意?)如何使我的視圖模型無摩擦和開發人員友好(即 - 映射應該自動工作控制器基類)?

我知道AutoMapper框架,我很可能會使用它。

因此,再次嘗試創建正確的視圖模型時常見的問題是什麼?如何構建它?如何在需要多個域對象輸入時完成映射?


我對查看需要來自多個聚合根的數據的情況感到困惑。我正在創建應用程序,其中包含圖書館,閱讀器,書目記錄等實體。

在我的情況下 - 在域級別,將所有這3種類型分組到LibraryReaderThatHasOrderedSomeBooks或什麼都沒有意義,但查看應顯示列表爲特定圖書館中的特定讀者訂購圖書需要全部。

所以 - 它似乎罰款來創建OrderedBooksListModel視圖模型視圖OrderedBooksList下保存LibraryOutputReaderOutputBibliographicRecordOutput視圖模型。甚至更好 - OrderedBooksListModel視圖模型,它利用flattening technique並擁有道具一樣ReaderFirstNameLibraryName

但是,因爲有多個輸入導致映射問題。
這不是1:1的關係,我只踢一個聚合根。
這是否意味着我的域模型是一種錯誤?

那麼純粹在UI層上生活的視圖模型字段(即枚舉,表明檢查選項卡)呢?

this大家在這種情況下做了什麼?

FooBarViewData fbvd = new FooBarViewData(); 
    fbvd.Foo = new Foo(){ A = "aaa"}; 
    fbvd.Bar = new Bar(){ B = "bbb"}; 
    return View(fbvd); 

我不願意這樣做=>

var fbvd = new FooBarViewData(); 
    fbvd.FooOutput = _mapper.Map<Foo,FooOutput>(new Foo(){ A = "aaa"}); 
    fbvd.BarOutput = _mapper.Map<Bar,BarOutput>(new Bar(){ B = "bbb"}); 
    return View(fbvd); 

好像很多寫作的。 :)


Reading this此刻。和this


好的。我想過這個問題有很多,是的 - 增加一個抽象層似乎是一個解決方案=>

alt text http://i46.tinypic.com/fe14qp.jpg

所以 - 在我的腦海這個已經工作,現在是時候爲一些玩弄。

TY吉米

回答

3

這很難定義所有這些,但在這裏。我們喜歡分離出我們稱之爲View從Controller構建的內容。該視圖看到一個扁平的,腦死的DTO樣物體。我們稱之爲視圖模型。

在控制器方面,我們構建了構建視圖模型所需的豐富圖表。這可能只是一個聚合根,也可能是多個聚合根的組合。所有這些共同組合成我們所說的演示模型。有時候,演示模型就是我們的持久性(域)模型,但有時它完全是一個新對象。但是,我們在實踐中發現,如果我們需要構建複合表示模型,它往往成爲相關行爲的一個磁鐵。

在你的例子中,我會創建一個ViewFooBarModel和一個ViewFooBarViewModel(或ViewFooBarModelDto)。然後我可以在我的控制器中討論ViewFooBarModel,然後依靠映射來使用AutoMapper從中間模型中得到我所需要的。

+0

希望看到你回答這個問題,你應該知道(http://www.lostechies.com/blogs/jimmy_bogard/archive/2010/01/04/ui-automation-tools-snake-oil.aspx)。對於這個問題的回答只是成功開發好的和可靠的UI測試(並準備Mvc2模板嗡嗡聲)的另一塊磚塊,我的實際目標是什麼。當我回家時,我會盡量總結整個想法 - 然後在你的答案下張貼另一個「ping」評論以獲得一些迴應。 :) – 2010-01-11 15:05:20

4

下面是對我們明白,我們一直在與長一段時間掙扎的替代品後一個項目:渲染數據是從接收數據不同。

我們使用ViewModels來渲染數據,但很快就發現,當通過表單發佈和類似的方式接收數據時,我們無法真正讓ViewModel適合ModelBinding的概念。主要原因是往返於瀏覽器往往涉及數據丟失。作爲一個例子,即使我們使用ViewModels,它們基於來自真實域對象的數據,但它們可能不公開所有來自域對象的數據。這意味着我們可能無法立即從瀏覽器發佈的數據中重建基礎域對象。

相反,我們需要使用映射器和存儲庫從發佈的數據中檢索完整的域對象。

我們意識到這一點之前,我們努力與很多試圖執行可能從重建發佈數據全域對象或視圖模型定製ModelBinders,但現在我們有獨立的PostModels該模型中,我們如何接收數據。

我們使用抽象映射器和服務將PostModel映射到域對象 - 如果有必要,可能還會返回ViewModel。

+0

這是一個很好的提示,但不幸(或幸運地)我已經想出了這部分。 Id/Mapping的模型綁定就像一個魅力。另一件事 - 將視圖模型分解爲您呈現的視圖模型並查看發佈表單時收到的模型是很好的。 – 2010-01-07 13:52:26

+0

我很感興趣,當查看需要多個實體視圖模型並且需要分組時,如何處理這些案例。有關於此的任何提示? – 2010-01-07 13:54:32

+0

我不確定我是否理解其他問題,但是您可以從其他ViewModels創建ViewModels。然而,你是一個聰明的人,所以你可能已經知道,所以我想你的意思是別的...... – 2010-01-07 14:01:54

3

雖然將無關的實體(或者他們的存儲庫)組合到域對象或服務中可能沒有意義,但將它們組合到表示層中可能會有很大的意義。

正如我們構建的自定義ViewModels以特別適合特定應用程序的方式表示域數據一樣,我們還使用自定義表示層服務,根據需要組合事物。這些服務比較特殊,因爲它們只是爲了支持某個特定的視圖而存在。

通常,我們會將此服務隱藏在接口後面,以便具體實現可以自由使用它需要組合所需結果的無關注入Domain對象。

+0

這對我也有意義。我只是想知道從技術角度來看實際的實施。我不願意創建無數的構造函數來聚合實體併產生更復雜的視圖模型。 automapper可以在這方面提供一些幫助嗎? – 2010-01-07 14:50:11

+0

我一直無法將我們的東西減少到某種不復雜的狀態。對於富客戶端來說更簡單,因爲您沒有全部的往返和數據丟失。我沒有看到AutoMapper在這方面提供了很多幫助,因爲它的強制是基於約定的映射。也許你應該問這個具體的問題作爲一個新的SO問題,然後我保證不回答:) – 2010-01-07 15:11:55

+0

想到一個想法=>可以用MapTo(typeof(OrderedBooksListModel))來修飾動作並調用匿名類型的視圖'View(「OrderedBooksList」,new {library,reader,bibliographicrecord []})'然後 - 通過過濾器,使用一些反射魔術和自動映射器正確映射它。這是一個可接受的解決方案嗎?有什麼缺點? – 2010-01-07 16:11:35

相關問題