c# - 如何将具有私有字典成员的类序列化到文件中?
问题描述
我正在尝试编写将类型(Dispatcher
如下所示的类型)保存到文件中的函数,然后稍后重新加载。我写了以下函数,但它们不起作用。我得到一个例外:
抛出异常:System.Xml.dll 中的“System.InvalidOperationException”
在其他地方我读到这可能是因为班级中的成员是私人的,那么我应该使用BinaryFormatter
,但它没有用。
我究竟做错了什么 ?
(Dispatcher
该类将用于存储消息,也将允许用户从中提取消息。所以我想备份数据以防出错,然后能够重新加载它)。
public class Dispatcher
{
private Dictionary<int, Dictionary<int, Dictionary<int, Message>>> m_DataBase;
private Dispatcher()
{
m_DataBase = new Dictionary<int, Dictionary<int, Dictionary<int, Message>>>();
}
public static Dispatcher LoadFromFile()
{
Dispatcher loadedDataBase;
try
{
using (Stream stream = new FileStream(@".\DispatcherDataBase.xml", FileMode.Open))
{
XmlSerializer serializer = new XmlSerializer(typeof(Dispatcher));
loadedDataBase = serializer.Deserialize(stream) as Dispatcher;
}
}
catch (Exception)
{
loadedDataBase = new Dispatcher();
}
return loadedDataBase;
}
public void SaveToFile()
{
FileMode wantedFileModeForStream;
try
{
if (File.Exists(@".\DispatcherDataBase.xml"))
{
wantedFileModeForStream = FileMode.Truncate;
}
else
{
wantedFileModeForStream = FileMode.CreateNew;
}
using (Stream stream = new FileStream(@".\DispatcherDataBase.xml", wantedFileModeForStream))
{
XmlSerializer serializer = new XmlSerializer(this.GetType());
serializer.Serialize(stream, this);
}
}
catch (Exception)
{
}
}
}
解决方案
您正在尝试使用XmlSerializer
序列化您的Dispatcher
类型并遇到三个不同的问题:
XmlSerializer
要求您的类型具有公共无参数构造函数。XmlSerializer
不支持字典。XmlSerializer
不会序列化非公共成员,例如m_DataBase
.
DataContractSerializer
(以及DataContractJsonSerializer
)没有这些限制。如果您使用数据协定属性Dispatcher
标记您的类型,您将能够使用此序列化程序将其序列化为 XML。
因此,如果您按如下方式修改您的类型:
public static class Constants
{
public const string DataContractNamespace = ""; // Or whatever
}
[DataContract(Name = "Dispatcher", Namespace = Constants.DataContractNamespace)]
public partial class Dispatcher
{
[DataMember]
private Dictionary<int, Dictionary<int, Dictionary<int, Message>>> m_DataBase;
private Dispatcher()
{
m_DataBase = new Dictionary<int, Dictionary<int, Dictionary<int, Message>>>();
}
[System.Runtime.Serialization.OnDeserialized]
void OnDeserializedMethod(System.Runtime.Serialization.StreamingContext context)
{
// Ensure m_DataBase is not null after deserialization (DataContractSerializer does not call the constructor).
if (m_DataBase == null)
m_DataBase = new Dictionary<int, Dictionary<int, Dictionary<int, Message>>>();
}
internal const string FileName = @"DispatcherDataBase.xml";
public static Dispatcher LoadFromFile()
{
Dispatcher loadedDataBase;
try
{
using (var stream = new FileStream(FileName, FileMode.Open))
{
var serializer = new DataContractSerializer(typeof(Dispatcher));
loadedDataBase = serializer.ReadObject(stream) as Dispatcher;
}
}
catch (Exception)
{
loadedDataBase = new Dispatcher();
}
return loadedDataBase;
}
public void SaveToFile()
{
using (var stream = new FileStream(FileName, FileMode.Create))
using (var writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true })) // Optional indentation for readability only.
{
var serializer = new DataContractSerializer(this.GetType());
serializer.WriteObject(writer, this);
}
}
}
// Not shown in question, added as an example
[DataContract(Name = "Message", Namespace = Constants.DataContractNamespace)]
public class Message
{
[DataMember]
public string Value { get; set; }
}
您将能够将您的课程往返Dispatcher
于 XML。演示小提琴#1在这里。
或者,您可以DataContractJsonSerializer
通过简单地交换序列化程序并消除可选的来使用并序列化为 JSON XmlWriter
:
public static Dispatcher LoadFromFile()
{
Dispatcher loadedDataBase;
try
{
using (var stream = new FileStream(FileName, FileMode.Open))
{
var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(Dispatcher));
loadedDataBase = serializer.ReadObject(stream) as Dispatcher;
}
}
catch (Exception)
{
loadedDataBase = new Dispatcher();
}
return loadedDataBase;
}
public void SaveToFile()
{
using (var stream = new FileStream(FileName, FileMode.Create))
{
var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(this.GetType());
serializer.WriteObject(stream, this);
}
}
Demo fiddle #2 here,它产生了一个相当简单、干净的序列化格式:
{"m_DataBase":[{"Key":1,"Value":[{"Key":2,"Value":[{"Key":3,"Value":{"Value":"hello"}}]}]}]}
如果您愿意使用 3rd 方组件,也可以使用json.net序列化此类型。
推荐阅读
- java - 搜索翻译的 id 时应该返回 null 还是 -1?
- java - 启动 jasperserver 失败:org.springframework.beans.factory.BeanCreationException
- swift - Firebase / Firestore - 完成块未按预期工作
- javascript - Python转javascript、js认证
- python - 动态数组python 3
- sql - 如何在 SQL 中特定列的重复行之后放置 0?
- java - 在火花集群环境上运行并行作业时火花数据集错误值
- .net - webapi使用Angular应用程序在跨域中丢失会话值
- mysql - 如何在参数之间组合多个
- python - APIView 类和 generics.GenericAPIView 有什么区别