任何人都可以理解为什么C#无法反序列化这个xml文件:
[Serializable()]
public class SerializableDictionary<TKey, TVal> : Dictionary<TKey, TVal>, IXmlSerializable, ISerializable {
private const string DictionaryNodeName = "Dictionary";
private const string ItemNodeName = "Item";
private const string KeyNodeName = "Key";
private const string ValueNodeName = "Value";
public SerializableDictionary() {
}
public SerializableDictionary(IDictionary<TKey, TVal> dictionary)
: base(dictionary) {
}
public SerializableDictionary(IEqualityComparer<TKey> comparer)
: base(comparer) {
}
public SerializableDictionary(int capacity)
: base(capacity) {
}
public SerializableDictionary(IDictionary<TKey, TVal> dictionary, IEqualityComparer<TKey> comparer)
: base(dictionary, comparer) {
}
public SerializableDictionary(int capacity, IEqualityComparer<TKey> comparer)
: base(capacity, comparer) {
}
protected SerializableDictionary(SerializationInfo info, StreamingContext context) {
int itemCount = info.GetInt32("ItemCount");
for (int i = 0; i < itemCount; i++) {
KeyValuePair<TKey, TVal> kvp = (KeyValuePair<TKey, TVal>)info.GetValue(String.Format("Item{0}", i), typeof(KeyValuePair<TKey, TVal>));
this.Add(kvp.Key, kvp.Value);
}
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue("ItemCount", this.Count);
int itemIdx = 0;
foreach (KeyValuePair<TKey, TVal> kvp in this) {
info.AddValue(String.Format("Item{0}", itemIdx), kvp, typeof(KeyValuePair<TKey, TVal>));
itemIdx++;
}
}
void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer) {
//writer.WriteStartElement(DictionaryNodeName);
foreach (KeyValuePair<TKey, TVal> kvp in this) {
writer.WriteStartElement(ItemNodeName);
writer.WriteStartElement(KeyNodeName);
KeySerializer.Serialize(writer, kvp.Key);
writer.WriteEndElement();
writer.WriteStartElement(ValueNodeName);
ValueSerializer.Serialize(writer, kvp.Value);
writer.WriteEndElement();
writer.WriteEndElement();
}
//writer.WriteEndElement();
}
void IXmlSerializable.ReadXml(System.Xml.XmlReader reader) {
if (reader.IsEmptyElement) {
return;
}
// Move past container
if (!reader.Read()) {
throw new XmlException("Error in Deserialization of Dictionary");
}
//reader.ReadStartElement(DictionaryNodeName);
while (reader.NodeType != XmlNodeType.EndElement) {
reader.ReadStartElement(ItemNodeName);
reader.ReadStartElement(KeyNodeName);
TKey key = (TKey)KeySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement(ValueNodeName);
TVal value = (TVal)ValueSerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadEndElement();
this.Add(key, value);
reader.MoveToContent();
}
//reader.ReadEndElement();
reader.ReadEndElement(); // Read End Element to close Read of containing node
}
System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema() {
return null;
}
protected XmlSerializer ValueSerializer {
get {
if (valueSerializer == null) {
valueSerializer = new XmlSerializer(typeof(TVal));
}
return valueSerializer;
}
}
private XmlSerializer KeySerializer {
get {
if (keySerializer == null) {
keySerializer = new XmlSerializer(typeof(TKey));
}
return keySerializer;
}
}
private XmlSerializer keySerializer = null;
private XmlSerializer valueSerializer = null;
}
它包含一个序列化字典,对于每个键,该值是一个序列化对象。如果值不是序列化对象,则字典可以正常工作。
使用XMLSerializer序列化序列化值和外部字典。
这是班级:
private SerializableDictionary<string, bool> alreadySeen;
...
public override object Snapshot(int snapshotId) {
XmlSerializer serializer = new XmlSerializer(typeof(SerializableDictionary<string, bool>));
StringWriter writer = new StringWriter();
serializer.Serialize(writer, alreadySeen);
return writer.ToString();
}
反序列化外部字典时出现问题。 感谢
更新:更多代码
以下是我生成字典值的方法:
public override Snapshot Snapshot(int snapshotId) {
var snapshot = new KeyedSnapshot(snapshotId);
// OperatorStatePerKey is a SerializableDictionary<string, object>
foreach (KeyValuePair<string, Operation> op in operations) {
snapshot.OperatorStatePerKey.Add(op.Key, op.Value.Snapshot(snapshotId)); // Here I'm calling the Snapshot function
}
return snapshot;
}
...
// Will serialize the Snapshot(1)
snapshotStore.Store(replicaId, Snapshot(1) as KeyedSnapshot);
以下是我在字典中插入序列化值的方法:
public void Store(int replicaId, KeyedSnapshot snapshot) {
// Serialize the snapshot and write it to a file
var xmlSerializer = new XmlSerializer(typeof(KeyedSnapshot));
var writer = new StreamWriter(prefix + replicaId + "." + snapshot.SnapshotId + ".snp", false);
xmlSerializer.Serialize(writer, snapshot);
writer.Close();
}
这是snapshotStore.Store实现:
XmlSerializer xmlSerializer = new XmlSerializer(typeof(KeyedSnapshot));
StreamReader reader = new StreamReader(filename);
// The error happens here
KeyedSnapshot k = (KeyedSnapshot)xmlSerializer.Deserialize(reader);
这就是我反序列化的方式:
System.InvalidOperationException: There is an error in XML document (2, 2). ---> System.InvalidOperationException: <NonKeyedSnapshot xmlns=''> was not expected.
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderKeyedSnapshot.Read4_KeyedSnapshot () [0x00064] in <ea86d900c5124263b557de9cd4c57fb0>:0
at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00038] in <8f2c484307284b51944a1a13a14c0266>:0
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Deserialize (System.Xml.XmlReader xmlReader, System.String encodingStyle, System.Xml.Serialization.XmlDeserializationEvents events) [0x00139] in <1140eab9e72948548294172a9716416d>:0
at System.Xml.Serialization.XmlSerializer.Deserialize (System.Xml.XmlReader xmlReader, System.String encodingStyle) [0x00000] in <1140eab9e72948548294172a9716416d>:0
at System.Xml.Serialization.XmlSerializer.Deserialize (System.IO.TextReader textReader) [0x0001c] in <1140eab9e72948548294172a9716416d>:0
at Task.Core.KeyedStateSnapshotStore.Retrieve (System.Int32 snapshotId) [0x0008b] in <3fdb7e68af394b91885b9dfe6ed8ba76>:0
最后,这是一个例外:
{{1}}