这是我的班级结构:
class DataItem
{
public string Id { get; set; }
public string Type { get; set; }
private Dictionary<string, DataProperty> properties = new Dictionary<string, DataProperty>();
public Dictionary<string, DataProperty> Properties
{
get { return properties; }
set { properties = value; }
}
}
public class DataProperty
{
public string Key { get; set; }
public string Value { get; set; }
public bool Required { get; set; }
}
这是我想要使用的XML(注意:我可以根据需要更改xml ):
<Data>
<DataItem>
<id>ph15</id>
<type>core</type>
<properties>
<DataProperty>
<key>size</key>
<value>50%</value>
<required>false</required>
</DataProperty>
<DataProperty>
<key>color</key>
<value>red</value>
<required>true</required>
</DataProperty>
</properties>
</DataItem>
<DataItem>
<id>ph234</id>
<type>core</type>
<properties>
</properties>
</DataItem>
</Data>
最终应将XML加载到另一个字典中:
private Dictionary<string, DataItem> Mydata;
答案 0 :(得分:3)
不幸的是,通用词典不是xml可序列化的。
解决方法是专门为一个单独的字段创建一个字段,以支持将字典元素公开为键/值对列表的序列化。然后,您还必须使用XmlIgnore
属性标记字典成员。
或者,您可以使用支持字典类型的XmlSerializer之外的其他内容(如DataContractSerializer)。
这是一个link to an article,它提供了一个很好的示例,说明如何使用字典修改类型以支持XML序列化。
如果您使用此代码,则一个重点 - 序列化的项目可能在输出中以任意顺序出现。这是使用dictinoaries(无序)作为数据存储模型的结果。
[XmlIgnore()]
public Dictionary<string, DataProperty> Properties
{
set { properties = value; }
get { return properties ; }
}
[XmlArray("Stuff")]
[XmlArrayItem("StuffLine", Type=typeof(DictionaryEntry))]
public DictionaryEntry[] PropertiesList
{
get
{
//Make an array of DictionaryEntries to return
DictionaryEntry[] ret=new DictionaryEntry[Properties.Count];
int i=0;
DictionaryEntry de;
//Iterate through Stuff to load items into the array.
foreach (KeyValuePair<string, DataProperty> props in Properties)
{
de = new DictionaryEntry();
de.Key = props.Key;
de.Value = props.Value;
ret[i]=de;
i++;
}
return ret;
}
set
{
Properties.Clear();
for (int i=0; i<value.Length; i++)
{
Properties.Add((string)value[i].Key, (DataProperty)value[i].Value);
}
}
}
答案 1 :(得分:2)
我知道之前已经回答了这个问题,但是因为我有一个非常简洁的方法(代码)用于使用DataContractSerializer类进行IDictionary序列化(由WCF使用,但可以并且应该在任何地方使用)我无法抗拒它这里:
public static class SerializationExtensions
{
public static string Serialize<T>(this T obj)
{
var serializer = new DataContractSerializer(obj.GetType());
using (var writer = new StringWriter())
using (var stm = new XmlTextWriter(writer))
{
serializer.WriteObject(stm, obj);
return writer.ToString();
}
}
public static T Deserialize<T>(this string serialized)
{
var serializer = new DataContractSerializer(typeof(T));
using (var reader = new StringReader(serialized))
using (var stm = new XmlTextReader(reader))
{
return (T)serializer.ReadObject(stm);
}
}
}
这在.NET 4中完美运行,并且也应该在.NET 3.5中运行,尽管我还没有测试它。我把流式传输到字符串因为它对我来说更方便,虽然我可以将一个较低级别的序列化引入Stream然后用它来序列化为字符串,但我倾向于仅在需要时进行推广(就像过早优化是邪恶的一样) ,所以这是过早的概括......)
用法非常简单:
// dictionary to serialize to string
Dictionary<string, object> myDict = new Dictionary<string, object>();
// add items to the dictionary...
myDict.Add(...);
// serialization is straight-forward
string serialized = myDict.Serialize();
...
// deserialization is just as simple
Dictionary<string, object> myDictCopy =
serialized.Deserialize<Dictionary<string,object>>();
myDictCopy将是myDict的逐字副本。
您还会注意到,所提供的泛型方法将能够序列化任何类型(据我所知),因为它不仅限于IDictionary接口,它实际上可以是任何泛型类型T.
希望有人帮助那里的人!
答案 2 :(得分:1)
我建议你使用DataContractSerializer。它确实支持词典。
答案 3 :(得分:1)
除此之外,另一种方法是创建一个包含Value和Key属性的简单对象。然后使用List(Of ThatObject),它应该工作。但这取决于您是否只想传输一个值键数据,因为所有其他属于字典的方法将无法使用。
答案 4 :(得分:0)
答案简短:你不能
这是因为即使您可以想象序列化方案,.NET Serializer也无法保证重新序列化的密钥具有相同的哈希值。
答案很长:你可以,但这是很多工作
您的解决方案是对整个对象进行手动序列化,或者使用包装IDictionary
的简单包装器属性替换Dictionary,但将其公开为对列表。 (如果需要,可以稍后转换。)
然而:这会留下与上面相同的问题,您无法保证重新序列化的密钥具有与序列化之前相同的哈希码。