2015-01-08 25 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; 
}