Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何序列化/反序列化词典<;字符串,对象>;转换为XML_C#_Xml - Fatal编程技术网

C# 如何序列化/反序列化词典<;字符串,对象>;转换为XML

C# 如何序列化/反序列化词典<;字符串,对象>;转换为XML,c#,xml,C#,Xml,我正在尝试为我的应用程序编写一个保存例程,其中应用程序的几个部分将项添加到字典中,然后save函数将它们写入XML文件。打开例程需要读取这些文件并重新填充字典,然后我可以将这些对象放回我的应用程序中。我正在为我现在的例行程序去序列化而挣扎。我的保存程序如下 XmlDocument xmlDoc = new XmlDocument(); // Write down the XML declaration XmlDeclaration xmlDeclaration = xmlDoc.CreateX

我正在尝试为我的应用程序编写一个保存例程,其中应用程序的几个部分将项添加到字典中,然后save函数将它们写入XML文件。打开例程需要读取这些文件并重新填充字典,然后我可以将这些对象放回我的应用程序中。我正在为我现在的例行程序去序列化而挣扎。我的保存程序如下

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的已知类型列表中。关于如何恰当地修饰它有什么想法吗?你是对的:必须为序列化程序提供已知的类型才能使用
字典
。我已经更新了我的答案以满足你的要求。可能不是最优雅的方式,但我发现它很有效。我做了类似的事情,但仍然有问题…我将用第二部分更新我的原始问题以详细说明。关于第二部分,我不确定这是一个框架还是。无论哪种方式,我刚刚摆脱了我的清单,在课堂上使用了可观察的收集,生活变得更轻松了。谢谢你在这方面的帮助。