C# 如何使用字符串数组值(反)序列化可序列化字典?
我需要将C#(.NET Framework 4.5.2)中的一个类与XML进行(反)序列化,该类的字典属性具有C# 如何使用字符串数组值(反)序列化可序列化字典?,c#,.net,dictionary,xml-serialization,C#,.net,Dictionary,Xml Serialization,我需要将C#(.NET Framework 4.5.2)中的一个类与XML进行(反)序列化,该类的字典属性具有string键和string[]数组值。我正在使用另一个问题中提到的SerializableDictionary实现,这意味着我的属性属于SerializableDictionary类型 将其序列化为XML文件看起来效果不错;但是,反序列化总是会因System.InvalidOperationException而失败 即使仅对字典本身进行反序列化,也会发生这种情况。请参阅下面的MSTes
string
键和string[]
数组值。我正在使用另一个问题中提到的SerializableDictionary
实现,这意味着我的属性属于SerializableDictionary
类型
将其序列化为XML文件看起来效果不错;但是,反序列化总是会因System.InvalidOperationException而失败
即使仅对字典本身进行反序列化,也会发生这种情况。请参阅下面的MSTest单元测试,它再现了问题:
使用系统;
使用Microsoft.VisualStudio.TestTools.UnitTesting;
使用My.Namespace.Collections;//其中定义了SerializableDictionary。
使用System.Xml.Serialization;
使用System.IO;
使用System.Linq;
命名空间My.namespace.Collections.Tests
{
///
///提供类的单元测试方法。
///
[测试类]
公共类SerializableDictionaryTests
{
///
///班级进行的基本测试
///(反)序列化。
///
[测试方法]
[超时(100)]
public void SerializableDictionary_BasicTest()
{
//安排。
var sourceDictionary=new SerializableDictionary();
可序列化的字典目的字典;
var serializer=新的XmlSerializer(typeof(SerializableDictionary));
var list1=新字符串[]{“苹果”、“香蕉”、“梨”};
var list2=新字符串[]{“胡萝卜”、“花椰菜”、“花椰菜”、“洋葱”};
var list3=新字符串[]{“牛肉”、“鸡肉”};
添加(“水果”,列表1);
添加(“蔬菜”,列表2);
添加(“肉类”,列表3);
//表演。
使用(var stream=new MemoryStream())
{
serializer.Serialize(流,sourceDictionary);
流位置=0;
destinationDictionary=(SerializableDictionary)序列化程序。反序列化(流);
}
//断言。
//注意:我们没有走到这一步,因为它在上面using块中的最后一条语句中崩溃。
AreEqual(3,destinationDictionary.Keys.Count);
Assert.IsTrue(destinationDictionary.ContainsKey(“果实”);
Assert.IsTrue(destinationDictionary.ContainsKey(“蔬菜”);
Assert.IsTrue(destinationDictionary.ContainsKey(“肉类”);
断言.AreEqual(3,destinationDictionary[“果实”]长度);
Assert.IsTrue(destinationDictionary[“水果”]。包含(“苹果”);
Assert.IsTrue(destinationDictionary[“水果”]。包含(“香蕉”);
Assert.IsTrue(destinationDictionary[“水果”]。包含(“梨”);
断言.AreEqual(4,destinationDictionary[“蔬菜”]长度);
Assert.IsTrue(destinationDictionary[“蔬菜”]。包含(“胡萝卜”);
Assert.IsTrue(destinationDictionary[“蔬菜”]。包含(“花椰菜”);
Assert.IsTrue(destinationDictionary[“蔬菜”]。包含(“花椰菜”);
Assert.IsTrue(destinationDictionary[“蔬菜”]。包含(“洋葱”);
断言.AreEqual(2,destinationDictionary[“meats”]长度);
Assert.IsTrue(destinationDictionary[“肉类”]。包含(“牛肉”);
Assert.IsTrue(destinationDictionary[“肉类”]。包含(“鸡肉”);
}
}
}
异常位于序列化程序。反序列化调用,并读取:
Test method My.Namespace.Collections.Tests.SerializableDictionaryTests.SerializableDictionary_BasicTest threw exception:
System.InvalidOperationException: There is an error in XML document (8, 8). ---> System.InvalidOperationException: There is an error in XML document (8, 8). ---> System.InvalidOperationException: <ArrayOfString xmlns=''> was not expected.
编辑#2:
在一些额外的测试之后,将测试中的SerializableDictionary
声明的TValue
类型更改为不同的内容,并检查它是否工作,如果TValue
是string
,我可以确认它工作正常,但是如果设置为,我的自定义可序列化类,即使该类用SerializableAttribute
修饰或实现IXmlSerializable
接口。因此,这个问题实际上比仅仅使用字符串数组更大。经过几天的努力,我得出结论,我使用的可序列化的实现不能用于处理数组和其他对象
我求助于在类上实现IXmlSerializable
接口,在WriteXml
方法中将字典值序列化为列表。在ReadXml
中,我只需对存储的列表进行反序列化,并将其值放回字典中,同时检查列表项上是否没有作为附加属性存储的重复键。它很笨重,但很有效。我很高兴您找到了解决方案,并成功地使其工作。不确定您是否仍然对解决方案持开放态度。尽管如此,以下是你可以做的事情,让你按照原样生活在Dictionary
尽管.NET的XmlSerializer
不支持字典,但有一些libs可以为您做到这一点。其中一个库是SharpSerializer(,),它将任何类型序列化为二进制或XML
使用非常简单:
var serializer = new SharpSerializer();
serializer.Serialize(dict, "test.xml");
输入
var dict = new Dictionary<string, string[]>
{
{ "nikhil", new string[] { "nikhil.0@so.com", "nikhil.1@so.com" } }
};
<Dictionary name="Root" type="System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<Items>
<Item>
<Simple value="nikhil" />
<SingleArray>
<Items>
<Simple value="nikhil.0@so.com" />
<Simple value="nikhil.1@so.com" />
</Items>
</SingleArray>
</Item>
</Items>
</Dictionary>
var dict=新字典
{
{“nikhil”,新字符串[]{“nikhil”。0@so.com“尼希尔。1@so.com" } }
};
输出
var dict = new Dictionary<string, string[]>
{
{ "nikhil", new string[] { "nikhil.0@so.com", "nikhil.1@so.com" } }
};
<Dictionary name="Root" type="System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<Items>
<Item>
<Simple value="nikhil" />
<SingleArray>
<Items>
<Simple value="nikhil.0@so.com" />
<Simple value="nikhil.1@so.com" />
</Items>
</SingleArray>
</Item>
</Items>
</Dictionary>
你考虑了这个答案吗?你能显示结果XML吗?@菲尔多,我认为这是最后一招。这实际上只是一个被序列化的更大的复合对象的一小部分,使用数据协定属性来修饰我的所有子类和属性可能需要一段时间