2015-01-08 50 views
0

假設我有以下代碼:版本控制:可能刪除WCF DataContract序列化中的列表元素?

namespace Test 
{ 
    [DataContract()] 
    internal class Class2 : AbstractSerializeableObject 
    { 
     [DataMember()] 
     int[] ints; 

     protected override XMLVersion ObjectVersion 
     { 
      get { return version; } 
     } 
     [DataMember()] 
     private XMLVersion version = new XMLVersion(1, 0, 0, "Test"); 

     protected override void SetDefaults() 
     { 
      ints = new int[] { 1, 2, 3, 4 }; 
     } 
    } 
} 

最終將序列化下列XML文件:

<?xml version="1.0" encoding="utf-8"?> 
<Class2 xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Test"> 
    <ints xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"> 
     <d2p1:int>1</d2p1:int> 
     <d2p1:int>2</d2p1:int> 
     <d2p1:int>3</d2p1:int> 
     <d2p1:int>4</d2p1:int> 
    </ints> 
    <version xmlns:d2p1="http://schemas.datacontract.org/2004/07/XMLSerializationLib"> 
     <d2p1:description></d2p1:description> 
     <d2p1:major>1</d2p1:major> 
     <d2p1:minor>0</d2p1:minor> 
     <d2p1:patch>0</d2p1:patch> 
     <d2p1:title>Test</d2p1:title> 
    </version> 
</Class2> 

現在我想從我的ints數組中刪除了幾個元素。我的AbstractSerializeableObject被設計爲SetDefaults在序列化或調用構造函數時被調用(與接受的答案here相同)問題是DataContractSerializer讀入整個集合的內容(不管有多少元素在默認數組)。因此,如果XML中有4個元素,我的默認值列表中有2個元素,那麼在我的反序列化數組中將會有4個元素。

有什麼辦法可以修復集合的大小,以便在反序列化時省略XML文件中的額外值?

+0

您不能更改數組的大小。爲什麼不使用列表? – ErnieL

+0

這不是問題;如果我使用列表,數組或字典,我會遇到同樣的問題;真的任何收藏。 – audiFanatic

+0

假設我在DataContract的第一個版本中用5個元素初始化數組。然後假設我對合同進行了修改,並用3個元素對其進行初始化。當來自前一個合同的XML文件使用新合同進行反序列化時,它將抽取5個元素,而不是3個。 – audiFanatic

回答

0

這種情況應該非常適合使用Data Contract Surrogates

數據契約替代是在數據 合同模型建立了一個先進的功能。此功能旨在用於 類型的定製和替換,用戶想要 更改某個類型的序列化,反序列化或投影到 元數據中的情況。可以使用代理的一些情況是,當沒有爲該類型指定數據 合同時,字段和屬性 未用DataMemberAttribute屬性標記,或者用戶希望 動態地創建模式變體。

當使用DataContractSerializer將.NET Framework從 轉換爲合適的格式(如XML)時,使用數據 合約代理來完成序列化和反序列化。數據合同 代用品也可用於在生成元數據表示(例如XML架構文檔 (XSD))時修改爲類型導出的元數據 。導入後,代碼將根據元數據創建,在這種情況下代理程序 也可用於自定義生成的代碼。

例如,你的情況 來讓這個只有2個元素都包含在序列化的XML:

public object GetObjectToSerialize(object obj, Type targetType) 
{ 
    Console.WriteLine("GetObjectToSerialize"); 
    if (obj is Class2) 
    { 
     Class2Surrogated c2sur = new Class2Surrogated(); 
     c2sur.ints = ((Class2Surrogated)obj).ints.Take(2).ToArray(); 
     c2sur.version = ((Class2Surrogated)obj).version; 
     return c2sur; 
    } 
    return obj; 
}