Why Xml-Serializable Class Need a Parameterless Constructor

Why XML-Serializable class need a parameterless constructor

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.

C# serialize a class without a parameterless constructor

Any Serializer Class need a parameterless constructor because, while deserializing it create an empty new instance, then it copies every public property taken from seialized data.

You can easily make the constructor private, if you want to avoid to create it without parameters.

EX:

public class PgpPublicKey
{
public PgpPublicKey(PublicKeyAlgorithmTag algorithm, AsymmetricKeyParameter pubKey, DateTime time);

private PgpPublicKey();
// cut other methods
}

XML cannot be serialized - parameterless constructor error, even with constructor

I figured it out...

I had been creating a new XmlSerializer and passing in a parameter as posted in a SO answer:

XmlSerializer xmlSer = new XmlSerializer(this.GetType());

When really it works perfectly fine to use the same XmlSerializer as the deserialization:

XmlSerializer objSer = new XmlSerializer(typeof(MyClass));

class can not do serialization without empty constructor

On deserialization XmlSerializer needs to create an object of your class, and then set its attributes one-by-one from the XML. In order to do so, the serializer must construct the object, and it uses the default parameterless constructor for that. It cannot use other constructors, because it does not know what attributes it needs to pass to them.

An inability to create instances of objects lacking parameterless constructors has been recognized as a problem, and fixed in the later versions of .NET by providing a backdoor way of creating uninitialized objects with FormatterServices.GetUninitializedObject. However, XMLSerializer has been left in its current state.

What role plays constructor in xmlserialize class?

The XmlSerializer will create instances of your types via reflection. To do so it must be able to instantiate your classes, which is by using its default-constructor. If you don´t have any, serializer can´t create the instance.

This is more or less the same thing, as serializer will do also:

Type type = // read type from XmlReader
var instance = Activator.CreateInstance(type);
property.SetProperty(instance, theValue);

Activator.CreateInstance however assumes a parameterless (=default) constructor. So if your class has another constructor defined, Activator can´t create the instance as it has no knowledge on the parameters to call the existing constructor, see here:

public class MyClass
{
public string MyString { get; set; }
public MyClass(string someString) { this.MyString = someString; }
}

Here Activator tries to create an instance of MyClass without any parameter, as it simply doesn´t know better. However MyClass excepts a string as parameter, making that call to fail.

If on the other hand MyClass has no constructor at all, the default-constructor is implicitely created for you. In this case you can savely create the instance via reflection.

XML serialization of subclass with no parameterless constructor

Is there actually a compelling reason for FlatEnvironment to be a subclass? It seems that it's not really serving any purpose other than producing an instance of the base class with certain values, in which case, you're probably better off just having a method that does that. This would solve your serialization problems:

// put this in the Environment class or a static class:
public const int PIXEL_PER_REAL_METER_RATIO = 100;
public static Environment FlatEnvironment(double realWidth, double realDepth, double maxHeight)
{
const int worldWidthSegments = 128;
const int worldDepthSegments = 128;
var heights = new System.Collections.Generic.List<short>();

for (int i = 0; i < (worldDepthSegments + 1) * (worldWidthSegments + 1); i++)
{
heights.Add(0);
}
return new Environment {
PIXEL_WIDTH = (int)realWidth * PIXEL_PER_REAL_METER_RATIO,
PIXEL_DEPTH = (int)realDepth * PIXEL_PER_REAL_METER_RATIO,
PIXEL_HEIGHT = (int)maxHeight * PIXEL_PER_REAL_METER_RATIO,
worldWidthSegments = worldWidthSegments,
worldDepthSegments = worldDepthSegments,
id = "FLAT_ENVIRONMENT-WxDxmH:" + realWidth + "x" + realDepth + "x" + maxHeight + "-PWxPDxPH:" + PIXEL_WIDTH + "x" + PIXEL_DEPTH + "x" + PIXEL_HEIGHT + " WSxDS:" + worldWidthSegments + "x" + worldDepthSegments,
realWidth = realWidth,
realDepth = realDepth,
realHeight = maxHeight,
};
}

How can I XML Serialize a Sealed Class with No Parameterless Constructor?

It's not possible to do directly; XmlSerializer can't cope with classes that don't have a parameterless constructor.

What I normally do is wrap the parameterless class in another class that's compatible with XML. The wrapper class has a parameterless constructor and a set of read-write properties; it has a FromXml method that calls the real class's constructor.

[XmlIgnore]
public SomeClass SomeProperty { get; set; }

[XmlElement("SomeProperty")]
public XmlSomeClass XmlSomeProperty
{
get { return XmlSomeClass.ToXml(SomeProperty); }
set { SomeProperty = value.FromXml(); }
}


Related Topics



Leave a reply



Submit