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
How to Give a C# Auto-Property an Initial Value
How to Decode HTML Characters in C#
String Representation of an Enum
Observablecollection Not Noticing When Item in It Changes (Even With Inotifypropertychanged)
What Are Regular Expression Balancing Groups
Add N Rectangles to Canvas With Mvvm in Wpf
Validation Failed For One or More Entities. See 'Entityvalidationerrors' Property For More Details
Entity Framework Code First - Two Foreign Keys from Same Table
Download Excel File Via Ajax MVC
Cannot Convert from List≪Derivedclass≫ to List≪Baseclass≫
C# Httpclient 4.5 Multipart/Form-Data Upload
The Provider Is Not Compatible With the Version of Oracle Client
Convert a Unicode String to an Escaped Ascii String
Entityframework - Contains Query of Composite Key
How to Cancel Task Await After a Timeout Period
Combining Two Expressions (Expression≪Func≪T, Bool≫≫)