字典XML序列化
我有一个类,我想序列化的字典属性。 我已经读过序列化字典不是直接可能的,所以我序列化/反序列化列表然后转换为字典。 它有效,但我想知道是否有一个正确的方法来做到这一点。
[Serializable] public class Album { private List photos = new List(); [XmlArray] public List Photos { get { return photos; } set { photos = value; } } private Dictionary dicoPhotos = new Dictionary(); [XmlIgnore] public Dictionary DicoPhotos { get { return dicoPhotos; } set { dicoPhotos = value; } } public void fillPhotosDictionnary() { this.dicoPhotos = this.photos.ToDictionary(p => p.Nom, p => p); } }
我试图在Photo的setter中填写字典,但它不起作用,我无法弄清楚为什么。
我建议利用DataContractSerializer
及其相关属性( DataContract
和DataMember
)。 它在.NET 3.0+中可用。
它与XmlSerializer
非常相似,但我发现它在一般序列化方面要好得多。 此外,它支持开箱即用的Dictionary
序列化。
在你的情况下,将一些属性切换到适当的DataContract属性应该是一个简单的事情,然后使用DataContractSerializer而不是XmlSerializer。
最后,输出将基本相同(XML文档),并且您的类中所需的代码更清晰。
[DataContract(Name = "Album", Namespace = "DataContracts")] public class Album { [DataMember(Name = "DicoPhotos")] private Dictionary dicoPhotos = new Dictionary(); public Dictionary DicoPhotos { get { return dicoPhotos; } set { dicoPhotos = value; } } }
DataContractSerializer周围有一些技巧和陷阱:
如果您仅为非持久性目的进行序列化(即通过电汇),请考虑使用NetDataContractSerializer。 如果你坚持使用任何类型的永久构造(如磁盘/数据库),或者你以后可能会有一个严重的问题(由于它的序列化方式),请不要使用它。
尝试使用Protobuf-net。 然后代码将类似于以下内容:
[Serializable] [ProtoContract] public class Album { private List photos = new List (); [ProtoMember(1)] public List Photos { get { return photos; } set { photos = value; } } private Dictionary dicoPhotos = new Dictionary(); [ProtoMember(2)] public Dictionary DicoPhotos { get { return dicoPhotos; } set { dicoPhotos = value; } } }
和序列化方法:
public void Serialize(Object obj, String FileFullPath) { byte[] serialized; using (var ms = new MemoryStream()) { Serializer.Serialize(ms, obj); serialized = ms.ToArray(); } File.WriteAllBytes(FileFullPath, serialized); }
它不起作用,因为XmlSerializer
一个接一个地存储列表中的项目,因此在反序列化期间不一定要调用setter。 你可以做几个选择:
- 构建一个实现
IList
的包装类,并将调用路由到底层字典; 要么 - 实现
IXmlSerializable
并自己完成整个类的(反)序列化; 要么 - 在反序列化之后调用“fix-up”方法(如你的
fillPhotosDictionnary
)。
就个人而言,我选择选项(1),因为Dictionary
序列化是一个常见问题,你也可能最终需要在其他类中使用它。
我意识到这个问题有点陈旧但我并不喜欢我找到的其他解决方案,因为他们以不同于我想要的方式格式化xml。 所以我这样做了。
我根据字典键创建了一个自定义动态类型,创建了这个新类型的实例,然后序列化该对象。
public void Serialize(string OutPath, Dictionary Input) { //Define stuff AssemblyName assName = new AssemblyName("CustomType"); AssemblyBuilder assBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assName, AssemblyBuilderAccess.RunAndSave); ModuleBuilder modBuilder = assBuilder.DefineDynamicModule(assName.Name); TypeBuilder typBuilder = modBuilder.DefineType("NewType", TypeAttributes.Public); //Add all the keys as fields foreach (string Key in Input.Keys) { typBuilder.DefineField(Key, Input[Key].GetType(), FieldAttributes.Public); } //Make the new type Type newType = typBuilder.CreateType(); //make instance object newInstance = Activator.CreateInstance(newType); //set Values foreach (string Key in Input.Keys) { newInstance.GetType().GetField(Key).SetValue(newInstance, Input[Key]); } //serialize XML XmlSerializer xs = new XmlSerializer(newType); TextWriter tw = new StreamWriter(OutPath); xs.Serialize(tw, newInstance); tw.Flush(); tw.Close(); }
如果要包含具有其他类型的原始字段的字典,可以在参数中包含该对象以传递值,并将这样的内容添加到适当的位置:
//This part adds the fields to the custom type, include near where the dictionary keys are being added as fields foreach (FieldInfo FI in InputObject.GetType().GetFields()) { if (FI.FieldType.IsPrimitive || FI.FieldType == typeof(string)) { FieldInfo fi = newInstance.GetType().GetField(FI.Name); fi.SetValue(newInstance, FI.GetValue(InputObject)); } } //This part adds the values to the object, include near where the values are being set foreach (FieldInfo FI in InputObject.GetType().GetFields()) { if (FI.FieldType.IsPrimitive || FI.FieldType == typeof(string)) { FieldBuilder fieBuilder = typBuilder.DefineField(FI.Name, FI.FieldType, FieldAttributes.Public); } }
这段代码:
//build dictionary Dictionary Input = new Dictionary(); Input.Add("Value1", "One"); Input.Add("Value2", "Two"); Input.Add("Value3", 3); Input.Add("Date", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); //Serialize! Serialize(FilePath, Input);
像这样构建一个xml输出:
- One Two 3 2014-08-28 18:03:58
然后你可以像这样读入/反序列化xml:
上述就是C#学习教程:字典XML序列化分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
public Dictionary Deserialize(string OutPath) { Dictionary Output = new Dictionary(); //create the xmlDocument XmlDocument xd = new XmlDocument(); xd.Load(XmlReader.Create(OutPath)); //Scan all the nodes in the main doc and add them to the dictionary //you can recursively check child nodes if your document requires. foreach (XmlNode node in xd.DocumentElement) { Output.Add(node.Name, node.InnerText); } return Output; }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/949501.html