Why XML-Serializable class need a parameterless constructor


Question

I'm writing code to do Xml serialization. With below function.

public static string SerializeToXml(object obj)
{
    XmlSerializer serializer = new XmlSerializer(obj.GetType());
    using (StringWriter writer = new StringWriter())
    {
        serializer.Serialize(writer, obj);
        return writer.ToString();
    }
}

If the argument is a instance of class without parameterless constructor, it will throw a exception.

Unhandled Exception: System.InvalidOperationException: CSharpConsole.Foo cannot be serialized because it does not have a parameterless constructor. at System.Xml.Serialization.TypeDesc.CheckSupported() at System.Xml.Serialization.TypeScope.GetTypeDesc(Type type, MemberInfo sourc e, Boolean directReference, Boolean throwOnError) at System.Xml.Serialization.ModelScope.GetTypeModel(Type type, Boolean direct Reference) at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type , XmlRootAttribute root, String defaultNamespace) at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultName space) at System.Xml.Serialization.XmlSerializer..ctor(Type type)

Why must there be a parameterless constructor in order to allow xml serialization to succeed?

EDIT: thanks for cfeduke's answer. The parameterless constructor can be private or internal.

2
167
7/1/2009 9:13:27 AM

Accepted Answer

During an object's de-serialization, the class responsible for de-serializing an object creates an instance of the serialized class and then proceeds to populate the serialized fields and properties only after acquiring an instance to populate.

You can make your constructor private or internal if you want, just so long as it's parameterless.

234
7/1/2018 9:21:15 PM

Exper Answer

This is a limitation of XmlSerializer. Note that BinaryFormatter and DataContractSerializer do not require this - they can create an uninitialized object out of the ether and initialize it during deserialization.

Since you are using xml, you might consider using DataContractSerializer and marking your class with [DataContract]/[DataMember], but note that this changes the schema (for example, there is no equivalent of [XmlAttribute] - everything becomes elements).

Update: if you really want to know, BinaryFormatter et al use FormatterServices.GetUninitializedObject() to create the object without invoking the constructor. Probably dangerous; I don't recommend using it too often ;-p See also the remarks on MSDN:

Because the new instance of the object is initialized to zero and no constructors are run, the object might not represent a state that is regarded as valid by that object. The current method should only be used for deserialization when the user intends to immediately populate all fields. It does not create an uninitialized string, since creating an empty instance of an immutable type serves no purpose.

I have my own serialization engine, but I don't intend making it use FormatterServices; I quite like knowing that a constructor (any constructor) has actually executed.

73
12/24/2008 5:17:08 PM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon