C# 如何序列化/反序列化词典<;字符串,对象>;转换为XML
我正在尝试为我的应用程序编写一个保存例程,其中应用程序的几个部分将项添加到字典中,然后save函数将它们写入XML文件。打开例程需要读取这些文件并重新填充字典,然后我可以将这些对象放回我的应用程序中。我正在为我现在的例行程序去序列化而挣扎。我的保存程序如下C# 如何序列化/反序列化词典<;字符串,对象>;转换为XML,c#,xml,C#,Xml,我正在尝试为我的应用程序编写一个保存例程,其中应用程序的几个部分将项添加到字典中,然后save函数将它们写入XML文件。打开例程需要读取这些文件并重新填充字典,然后我可以将这些对象放回我的应用程序中。我正在为我现在的例行程序去序列化而挣扎。我的保存程序如下 XmlDocument xmlDoc = new XmlDocument(); // Write down the XML declaration XmlDeclaration xmlDeclaration = xmlDoc.CreateX
XmlDocument xmlDoc = new XmlDocument();
// Write down the XML declaration
XmlDeclaration xmlDeclaration = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
// Create the root element
XmlElement rootNode = xmlDoc.CreateElement("TireStudy");
xmlDoc.InsertBefore(xmlDeclaration, xmlDoc.DocumentElement);
xmlDoc.AppendChild(rootNode);
foreach (var saveItem in _SaveItems)
{
XPathNavigator nav = rootNode.CreateNavigator();
using (var writer = nav.AppendChild())
{
var serializer = new XmlSerializer(saveItem.Value.GetType());
writer.WriteWhitespace("");
serializer.Serialize(writer, saveItem.Value);
writer.Close();
}
}
xmlDoc.Save(fileName);
此例程用于创建文件,但我希望字典的键值也保存在文件中,并且我不确定如何对由此创建的文件进行反序列化,因为我在读取对象之前不知道对象的类型
第2部分(我讨厌在问题中添加新的部分,但我看不到更好的方法来解决未来的问题)
我现在有以下代码
var knownTypes = new List<Type>
{
typeof(ObservableCollection<string>),
typeof(ObservableCollection<Segments>),
typeof(Segments),
typeof(List<string>)
};
var serialized = _SaveItems.Serialize(knownTypes);
var knownTypes=新列表
{
类型(可观测采集),
类型(可观测采集),
(段)的类型,
类型(列表)
};
var serialized=_SaveItems.Serialize(knownTypes);
但我有以下例外
Type 'System.Collections.Generic.List`1[System.String]' cannot be added to list of known types since another type 'System.Collections.ObjectModel.ObservableCollection`1[System.String]' with the same data contract name 'http://schemas.microsoft.com/2003/10/Serialization/Arrays:ArrayOfstring' is already present. If there are different collections of a particular type - for example, List<Test> and Test[], they cannot both be added as known types. Consider specifying only one of these types for addition to the known types list.
Type'System.Collections.Generic.List`1[System.String]'无法添加到已知类型的列表中,因为另一个类型'System.Collections.ObjectModel.observeCollection`1[System.String]'具有相同的数据协定名称'http://schemas.microsoft.com/2003/10/Serialization/Arrays:ArrayOfstring"已经出现了。如果存在特定类型的不同集合(例如,List和Test[]),则不能将它们都添加为已知类型。考虑仅指定这些类型中的一种用于添加已知类型列表。
如果我删除typeof(ObservableCollection)或typeof(List),它需要我删除的类型。您可以使用
DataContractSerializer
,如本文所述,但您可能必须将已知类型作为参数传递给序列化程序,以支持嵌套的对象
类型化类:
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.IO;
using System.Xml;
public static class SerializationExtensions
{
public static string Serialize<T>(this T obj, IEnumerable<Type> knownTypes)
{
var serializer = new DataContractSerializer(obj.GetType(), knownTypes);
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, IEnumerable<Type> knownTypes)
{
var serializer = new DataContractSerializer(typeof(T), knownTypes);
using (var reader = new StringReader(serialized))
using (var stm = new XmlTextReader(reader))
{
return (T)serializer.ReadObject(stm);
}
}
}
public class Address
{
public string Country { get; set; }
public string City { get; set; }
}
public class CodedAddress
{
public int CountryCode { get; set; }
public int CityCode { get; set; }
}
class Program
{
static void Main(string[] args)
{
var persons1 = new Dictionary<string, Address>();
persons1.Add("John Smith", new Address { Country = "US", City = "New York" });
persons1.Add("Jean Martin", new Address { Country = "France", City = "Paris" });
// no need to provide known types to the serializer
var serializedPersons1 = persons1.Serialize(null);
var deserializedPersons1 = serializedPersons1.Deserialize<Dictionary<string, Address>>(null);
var persons2 = new Dictionary<string, object>();
persons2.Add("John Smith", new Address { Country = "US", City = "New York" });
persons2.Add("Jean Martin", new CodedAddress { CountryCode = 33, CityCode = 75 });
// must provide known types to the serializer
var knownTypes = new List<Type> { typeof(Address), typeof(CodedAddress) };
var serializedPersons2 = persons2.Serialize(knownTypes);
var deserializedPersons2 = serializedPersons2.Deserialize<Dictionary<string, object>>(knownTypes);
}
}
使用系统;
使用System.Collections.Generic;
使用System.Runtime.Serialization;
使用System.IO;
使用System.Xml;
公共静态类序列化扩展
{
公共静态字符串序列化(此T对象,IEnumerable knownTypes)
{
var serializer=新的DataContractSerializer(obj.GetType(),knownTypes);
使用(var writer=new StringWriter())
使用(var stm=new XmlTextWriter(writer))
{
serializer.WriteObject(stm,obj);
返回writer.ToString();
}
}
公共静态T反序列化(此字符串已序列化,IEnumerable knownTypes)
{
var serializer=新的DataContractSerializer(typeof(T),knownTypes);
使用(var reader=newstringreader(序列化))
使用(var stm=新的XmlTextReader(reader))
{
return(T)serializer.ReadObject(stm);
}
}
}
公共课堂演讲
{
公共字符串国家{get;set;}
公共字符串City{get;set;}
}
公营服装
{
公共国际国家代码{get;set;}
公共int城市代码{get;set;}
}
班级计划
{
静态void Main(字符串[]参数)
{
var persons1=新字典();
人员1.添加(“约翰·史密斯”,新地址{Country=“US”,City=“new York”});
人员1.添加(“Jean Martin”,新地址{Country=“France”,City=“Paris”});
//无需向序列化程序提供已知类型
var serializedPersons1=persons1.Serialize(null);
var deserializedPersons1=serializedPersons1.Deserialize(null);
var persons2=新字典();
人员2.添加(“约翰·史密斯”,新地址{Country=“US”,City=“new York”});
人员2.添加(“Jean Martin”,新代码地址{CountryCode=33,CityCode=75});
//必须向序列化程序提供已知类型
var knownTypes=新列表{typeof(Address),typeof(CodedAddress)};
var serializedPersons2=persons2.Serialize(knownTypes);
var deserializedPersons2=serializedPersons2.Deserialize(knownTypes);
}
}
我的google fu在这方面严重不足。昨天的大部分时间我都在研究这件事,但没有想到这一点,否则我就失去了意义。让我尝试一下,然后再与您联系。我在序列化时遇到以下异常-不应键入数据协定名称为“SitesViewModel:”的“MyProgram.InformationTabs.NavigationTrees.SitesViewModel”。考虑使用DATACONTRORTCORDEVER或将未知类型的任何类型添加到已知类型的列表中,例如,使用NoNyType属性或将它们添加到传递给DATACONTROTTRORIGLASER的已知类型列表中。关于如何恰当地修饰它有什么想法吗?你是对的:必须为序列化程序提供已知的类型才能使用字典。我已经更新了我的答案以满足你的要求。可能不是最优雅的方式,但我发现它很有效。我做了类似的事情,但仍然有问题…我将用第二部分更新我的原始问题以详细说明。关于第二部分,我不确定这是一个框架还是。无论哪种方式,我刚刚摆脱了我的清单,在课堂上使用了可观察的收集,生活变得更轻松了。谢谢你在这方面的帮助。