2009-11-13 92 views
1

好的,所以我參與了創建DTO的漫長過程,以便通過電線發送我的模型,我不覺得我要走正確的路線。WCF DataMember序列化問題

我的問題是,我的模型中的大部分實體並不多於DTO。我基本上有一個貧血的領域模型,這很好,但它也讓我想知道是否需要爲這些實體建模DTO。

所以,我的第一個問題是,如果只是序列化我的實體並通過線路傳遞這些信息,可能會遇到什麼問題?

其次,一個更具體的問題給出像這樣的屬性簽名:

public virtual Unit Unit { get; set; } 

是否有可能,我只是在導線上的單元ID而不是序列化單元對象發送?

編輯: 對不起,我不清楚我的問題,因爲你們發佈我知道我只能指定單位的Id屬性,但這不會爲我工作。

原因是這個屬性(上面)是在「Country」類上的,我希望UnitID只在我調用「CountryService.GetCountry(Id)」時纔會返回或類似。但在浮動服務調用「UnitService.GetUnit(Id)」我想要更多的屬性被序列化並通過電線發送。 希望這是有道理的。

謝謝,克里斯。

回答

1

其次,一個更具體的問題給出一個屬性簽名像這樣:

public virtual Unit Unit { get; set; }

是否有可能,我只是把線路上的UnitID和 不序列化單元發送目的?

當然 - 確保

  1. 沒有標記您Unit財產與[DataMember]
  2. 創建一個名爲UnitId第二個屬性,你馬克數據成員
  3. 確保你的客戶總是可以從以某種方式重建Unit

UPDATE:

的原因是,這家酒店 (上圖)是一個 「國家」 級和我 希望的UnitID只返回時,我 呼叫「CountryService.GetCountry (Id)「 或simmilar。但在浮動 服務調用「UnitService。GetUnit(ID)」 我想更多的屬性是 序列化並通過網絡發送 希望這是有道理

在這種情況下,你需要兩個獨立的DataContracts - 。一個是CountryService.GetCountry(Id)呼叫只用在它UnitId,和另一個用於UnitService.GetUnit(Id)通話用的Unit所有屬性要在它

無法有條件地發送一些特性 - 與否 - 這取決於運行時決定DataContracts在XML架構爲藍本,如果你有兩套你需要的屬性,y您需要兩個獨立的DataContracts。

0

通過添加NonSerializedAttribute(msdn),可以縮小將通過電線傳遞的對象的大小。你仍然會得到Unit,但只有UnitId。

我不認爲只是序列化你的DTO會有問題。 您是否使用DTO中的所有信息? 你是否跨越了域界限?我會在每個域中創建新的實體併爲它們製作映射器。

0

從我所能理解的,你的問題源於你有一個由你的DTO製作的本地顯式聲明的對象圖的事實。我的意思是你已經在你的Country模型上聲明public Unit Unit { get; set; }(不知道你爲什麼聲明它們是virtual,但這與手頭的問題沒有直接關係),而不是嘗試一種方法來保證對象圖簡化爲簡併案例的單個對象圖節點。

例如,考慮形式public UnitID Unit { get; set; }定義「參照」財產上的模型,其中UnitID實際上可能intGuid或者你用它來相互唯一識別和區分Unit模型。只要你有一個引用或一組引用另一個模型,用它的標識符類型而不是它的實際類型替換它。這種策略適用於一套持久的模型,例如從/到每個模型具有身份密鑰的數據庫。這樣做可以讓你簡單的序列化,而不必擔心循環引用,因爲它們現在是不可能的。從技術上講,沒有更多的引用(即直接引用;它們現在是間接引用)。我們現在只是在您的領域模型設計中添加一個間接層。現在我們來適應那個間接層。

既然你聲稱你對貧血域模型方法很好,那麼這應該與此相適應。你付出的間接的未成年人(恕我直言)成本模型的設計和交易它的主要(恕我直言)基於接口的方法的好處數據檢索:

public interface IUnitRepository { 
    Unit GetUnit(UnitID id); 
    IEnumerable<Unit> GetUnits(IEnumerable<UnitID> ids); 
    // etc. 
} 

在你的消費者的代碼(即代碼使用此接口和域模型),通過執​​行接口調用以獲取由間接引用指向的基礎模型來遍歷隱含對象圖只會稍微複雜一些。

BEFORE:

Country ct = ...; // I assume you have this reference already 
Unit ut = ct.Unit; 

AFTER:

// Somewhere earlier in your code, i.e. not *every* time this type of code appears 
IUnitsRepository repo = new SomeUnitsRepositoryImpl(); 
Country ct = ...; // I assume you have this reference already 
Unit ut = repo.GetUnit(ct.UnitID); 

如果這句法困擾你,你可以定義上鍵入形式的Country一套擴展的方法:

public static Unit Unit(this Country c, IUnitsRepository repo) { 
    return repo.GetUnit(c.UnitID); 
} 

擴展方法後:

IUnitsRepository repo = new SomeUnitsRepositoryImpl(); 
Country ct = ...; // I assume you have this reference already 
Unit ut = ct.Unit(repo); 

基於接口的方法可以爲您帶來經典的一系列優點,如關注點分離,可測試性,消費者與生產者絕緣等等。此外,您現在可以通過接口的實現類型更直接地控制對象的生命週期。我的意思是,你不應該假設你的Unit GetUnit(UnitID id)方法的實施是天真的。此方法現在可以使用與SomeUnitsRepositoryImpl的實例綁定的Dictionary<UnitID, Unit>執行一些本地內存緩存。

有點囉嗦,但我希望它有幫助。彷彿從提供的細節數量來看,這並不明顯,我目前正在我的工作地點開展這項設計,以處理我們的記錄數據庫系統。 :)我真的非常喜歡它給我所有的靈活性,只需在域模型的設計中增加一層間接尋址的簡單代價。

+0

好吧,所以屬性是虛擬的原因是因爲我正在使用和ORM(NHibernate在這種情況下),它需要我的POCO國家對象,並圍繞它建立一個代理來自動掛鉤延遲加載相關對象(即單位這個案例)。現在,我可以讓Country對象與您聲明的任何其他模型沒有關係,但這意味着要手動創建所有這些管道工作。這對我來說不是一個好的折衷,因爲我認爲序列化程序應該足夠靈活,可以讓我採用複雜的模型,只顯示我選擇的內容。我最終選擇了AutoMapper – Owen 2009-12-21 23:06:25