我正在编写代码来执行Xml序列化。使用下面的函数。
public static string SerializeToXml(object obj)
{
XmlSerializer serializer = new XmlSerializer(obj.GetType());
using (StringWriter writer = new StringWriter())
{
serializer.Serialize(writer, obj);
return writer.ToString();
}
}如果参数是没有无参数构造函数的类的实例,它将抛出异常。
未处理的异常: System.InvalidOperationException: CSharpConsole.Foo无法序列化,因为它没有无参数的构造函数。at System.Xml.Serialization.TypeDesc.CheckSupported() at System.Xml.Serialization.TypeScope.GetTypeDesc(Type类型,字符串来源e,Boolean directReference,Boolean throwOnError) at System.Xml.Serialization.ModelScope.GetTypeModel(Type类型,Boolean直接引用) at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type类型,字符串根,String defaultNamespace) at System.Xml.Serialization.XmlSerializer..ctor(Type类型,字符串空间) at System.Xml.Serialization.XmlSerializer..ctor(Type类型)
为什么必须有一个无参数的构造函数才能使xml序列化成功?
编辑:感谢cfeduke的回答。无参数构造函数可以是私有的,也可以是内部的。
发布于 2008-11-06 05:37:22
在对象的反序列化期间,负责反序列化对象的类创建序列化的类的实例,然后仅在获取要填充的实例之后才继续填充序列化的字段和属性。
如果你愿意,你可以让你的构造函数成为private或者internal,只要它是无参数的。
发布于 2008-11-06 08:02:33
这是XmlSerializer的一个限制。请注意,BinaryFormatter和DataContractSerializer不需要这样做-它们可以在反序列化过程中创建一个未初始化的对象并对其进行初始化。
因为您使用的是xml,所以可以考虑使用DataContractSerializer并用[DataContract]/[DataMember标记您的类],但请注意,这会改变模式(例如,没有[XmlAttribute]的等价物-一切都变成了元素)。
更新:如果你真的想知道,BinaryFormatter等人使用FormatterServices.GetUninitializedObject()来创建对象,而不调用构造函数。可能很危险;我不建议经常使用它;-p参见MSDN上的备注:
因为该对象的新实例被初始化为零并且没有运行任何构造函数,所以该对象可能不表示该对象认为有效的状态。仅当用户打算立即填充所有字段时,才应使用当前方法进行反序列化。它不会创建未初始化的字符串,因为创建不可变类型的空实例没有任何作用。
我有我的own序列化引擎,但我不打算让它使用FormatterServices;我非常喜欢知道构造函数(任何构造函数)已经实际执行了。
发布于 2019-11-03 03:57:13
答案是:没有任何好的理由。
与其名称相反,XmlSerializer类不仅用于序列化,还用于反序列化。它对您的类执行某些检查以确保它将工作,其中一些检查只与反序列化相关,但无论如何它都会执行所有检查,因为它不知道您稍后要做什么。
您的类未能通过的检查是仅与反序列化相关的检查之一。下面是发生的情况:
XmlSerializer类将需要创建您的类型的实例。XmlSerializer的构造函数,它不能调用除无参数构造函数之外的任何构造函数,因为它不知道要传递什么参数给接受参数的构造函数。因此,它会检查您的类是否有无参数的构造函数,因为没有,所以它会失败。因此,如果XmlSerializer类的编写方式是只执行与序列化相关的检查,那么您的类就会通过,因为序列化绝对不需要使用无参数构造函数。
正如其他人已经指出的,问题的快速解决方案是简单地添加一个无参数构造函数。不幸的是,这也是一个糟糕的解决方案,因为它意味着您不能从构造函数参数初始化任何readonly成员。
除此之外,XmlSerializer类的编写方式甚至可以在没有无参数构造函数的情况下实现类的反序列化。所有需要做的就是使用"The Factory Method Design Pattern" (Wikipedia)。从外观上看,微软认为这种设计模式对于DotNet程序员来说太高级了,显然他们不应该对这些事情感到不必要的困惑。因此,根据微软的说法,DotNet程序员最好坚持使用无参数构造函数。
https://stackoverflow.com/questions/267724
复制相似问题