NetDataContractSerializer序列化Dictionary<> .Comparer - DataContractSerializer不?

时间:2017-01-11 13:40:20

标签: c# .net xml wcf serialization

从.NET源代码我看到Dictionary<TKey,TValue>实现ISerializable,因此方法:void GetObjectData(SerializationInfo info, StreamingContext context);

GetObjectData()看来Comparer确实已将SerializationInfo添加为[System.Security.SecurityCritical] // auto-generated_required public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { ... info.AddValue(VersionName, version); #if FEATURE_RANDOMIZED_STRING_HASHING info.AddValue(ComparerName, HashHelpers.GetEqualityComparerForSerialization(comparer), typeof(IEqualityComparer<TKey>)); #else info.AddValue(ComparerName, comparer, typeof(IEqualityComparer<TKey>)); #endif info.AddValue(HashSizeName, buckets == null ? 0 : buckets.Length); //This is the length of the bucket array. ... } 实例的值,根据MSDN docs; 存储序列化或反序列化对象所需的所有数据

DataContractSerializer

...但是,实际上,这取决于是使用NetDataContractSerializer还是using System; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization; using System.Text; namespace ConsoleApplication2 { public class Program2 { public static void Main(string[] args) { var dict = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase) { {"k", 123} }; // Prints: "OrdinalComparer" Console.WriteLine(dict.Comparer.GetType().Name); // Using DataContractSerializer (DCS) var dcsXml = SerializeWithDcs(dict); var dcsDict = DeserializeWithDcs<Dictionary<string, int>>(dcsXml); // Prints: "GenericEqualityComparer`1" Console.WriteLine(dcsDict.Comparer.GetType().Name); // Using NetDataContractSerializer (NetDCS) var netDcsXml = SerializeWithNetDcs(dict); var netDcsDict = DeserializeWithNetDcs<Dictionary<string, int>>(netDcsXml); // Prints: "OrdinalComparer" Console.WriteLine(netDcsDict.Comparer.GetType().Name); Console.ReadLine(); } private static string SerializeWithDcs<T>(T obj) { using (var ms = new MemoryStream()) { using (var sr = new StreamReader(ms, Encoding.UTF8)) { var serializer = new DataContractSerializer(typeof(T)); serializer.WriteObject(ms, obj); ms.Position = 0; return sr.ReadToEnd(); } } } private static T DeserializeWithDcs<T>(string xml) { using (var ms = new MemoryStream()) { using (var sw = new StreamWriter(ms, Encoding.UTF8)) { sw.Write(xml); sw.Flush(); ms.Position = 0; var deserializer = new DataContractSerializer(typeof(T)); return (T)deserializer.ReadObject(ms); } } } private static string SerializeWithNetDcs(object obj) { using (var ms = new MemoryStream()) { using (var sr = new StreamReader(ms, Encoding.UTF8)) { var serializer = new NetDataContractSerializer(); serializer.WriteObject(ms, obj); ms.Position = 0; return sr.ReadToEnd(); } } } private static T DeserializeWithNetDcs<T>(string xml) { using (var ms = new MemoryStream()) { using (var sw = new StreamWriter(ms, Encoding.UTF8)) { sw.Write(xml); sw.Flush(); ms.Position = 0; var deserializer = new NetDataContractSerializer(); return (T)deserializer.ReadObject(ms); } } } } } 。以下是一个完整的例子:

DataContractSerializer

<ArrayOfKeyValueOfstringint xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <KeyValueOfstringint> <Key>k</Key> <Value>123</Value> </KeyValueOfstringint> </ArrayOfKeyValueOfstringint> 输出XML:

NetDataContractSerializer

<ArrayOfKeyValueOfstringint z:Id="1" z:Type="System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]" z:Assembly="0" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"> <Version z:Id="2" z:Type="System.Int32" z:Assembly="0" xmlns="">1</Version> <Comparer z:Id="3" z:Type="System.OrdinalComparer" z:Assembly="0" xmlns=""> <_ignoreCase xmlns="http://schemas.datacontract.org/2004/07/System">true</_ignoreCase> </Comparer> <HashSize z:Id="4" z:Type="System.Int32" z:Assembly="0" xmlns="">3</HashSize> <KeyValuePairs z:Id="5" z:Type="System.Collections.Generic.KeyValuePair`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]][]" z:Assembly="0" z:Size="1" xmlns=""> <KeyValuePairOfstringint xmlns="http://schemas.datacontract.org/2004/07/System.Collections.Generic"> <key z:Id="6">k</key> <value>123</value> </KeyValuePairOfstringint> </KeyValuePairs> </ArrayOfKeyValueOfstringint> 输出XML:

Comparer

从XML中可以明显看出,DataContractSerializer在使用DataContractSerializer进行序列化/反序列化时已经消失了 - 它根本就不在XML中。

将类型添加到DataContractSerializer的已知类型中,没有任何区别。

我见过类似的问题(XML serialization of a Dictionary with a custom IEqualityComparerHow do you get WCF serialization to preserve a non-default Comparer on a generic Dictionary?)但据我所知,没有人真正解决这种行为背后的原因,我想理解为什么{{1 }}跳过GetObjectData()并因此序列化Comparer

0 个答案:

没有答案