我有以下课程:
[Serializable]
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Dictionary<string, string> Attributes { get; set; }
}
我想使用XmlSerializer对其进行序列化并获得以下输出:
<Person>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Attributes>
<PhoneNumber>12345</PhoneNumber>
<StreetName>...</StreetName>
<StreetNumber>...</StreetNumber>
...
</Attributes>
</Person>
任何帮助都将不胜感激。
答案 0 :(得分:2)
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
namespace CSharpSampleApplication.Data.CoreObjects
{
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
bool wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
return;
while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement("item");
reader.ReadStartElement("key");
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("value");
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
this.Add(key, value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
foreach (TKey key in this.Keys)
{
writer.WriteStartElement("item");
writer.WriteStartElement("key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
writer.WriteStartElement("value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
#endregion
}
}
答案 1 :(得分:2)
与MrFox的答案类似,这是我过去使用过的hack,它已经足够好了。
public class Foo{
[XmlIgnore()]
public Dictionary<string,string> Dct{get;set;}
[XmlAttribute]
public string SerializedDictionary{
get{
StringBuilder s = new StringBuilder();
foreach(var kvp in Dct){
if (s.Length > 0) s.Append("|");
s.AppendFormat("{0},{1}", kvp.Key, kvp.Value);
}
return s.ToString();
}
set{
string[] aKvps = value.Split('|');
Dct = new Dictionary<string,string>();
for(int i=0; i<aKvps.Length; ++i){
string aPair = aKvps[i].Split(',');
if (aPair.Length == 2)
Dct.Add(aPair[0], aPair[1]);
}
}
}
}
我从内存中输入了这个,并没有尝试编译它,所以可能有一两个bug。但希望它可以解决这个问题。此外,这假设您的数据在值的键中没有逗号或管道。如果是这种情况,此解决方案可能对您不起作用。
答案 2 :(得分:1)
我以前做过这个:
/// <summary>
/// Save all information needed set current game state into given file.
/// </summary>
/// <param name="fileName"></param>
public void save(string fileName)
{
Dictionary<string, string> attributes = new Dictionary<string, string>();
attributes.Add("blue", "very");
attributes.Add("red", "not");
Stream stream = File.Open(fileName, FileMode.Create);
BinaryFormatter bFormatter = new BinaryFormatter();
// Request the current state of all registered
// objects and save them into the file.
foreach (KeyValuePair<string, string> storeOnDisk in attributes)
bFormatter.Serialize(stream, storeOnDisk);
stream.Close();
}
答案 3 :(得分:0)
为什么不使用Protocol Buffer进行序列化。它是开源和免费平台,您可以将它与Java,C ++和Python一起使用。这是一个提示。
答案 4 :(得分:0)
因为无法在dotnet中序列化字典。我的解决方案是:
输出:
**<Person>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Attributes>
<PhoneNumber>12345</PhoneNumber>
<StreetName>StackOverFlow Street</StreetName>
<StreetNumber>51</StreetNumber>
</Attributes>
</Person>**
核心代码
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Dictionary<string, string> Attributes { get; set; }
}
public class DictionarySerializer
{
private StringBuilder _sBuilder;
private XmlWriterSettings _writerSettings;
private XmlWriter w;
public string WriteXml(Person personObject)
{
_sBuilder = new StringBuilder();
_writerSettings = new XmlWriterSettings();
_writerSettings.Indent = true;
_writerSettings.OmitXmlDeclaration = true;
w = XmlWriter.Create(_sBuilder, _writerSettings);
//if you remove person properties any dictionary can be turned into XML.
w.WriteStartElement("Person");
w.WriteElementString("FirstName", personObject.FirstName);
w.WriteElementString("LastName", personObject.LastName);
w.WriteStartElement("Attributes");
foreach (var item in personObject.Attributes)
{
w.WriteElementString(item.Key, item.Value);
}
w.WriteEndElement();
w.WriteEndElement();
w.Close();
return _sBuilder.ToString();
}
}
使用代码
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Person objP = new Person();
objP.FirstName = "John";
objP.LastName = "Doe";
objP.Attributes = new Dictionary<string, string>();
objP.Attributes.Add("PhoneNumber", "12345");
objP.Attributes.Add("StreetName", "StackOverFlow Street");
objP.Attributes.Add("StreetNumber", "51");
DictionarySerializer ds = new DictionarySerializer();
string val = ds.WriteXml(objP);
}
}