Asked  7 Months ago    Answers:  5   Viewed   145 times

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.

 Answers

49

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.

Tuesday, June 1, 2021
 
njai
answered 7 Months ago
20

No it is nothing about MVC (sorry, I've misread your post). It is only about plain C#'py object creation. You see, take this class for an example:

public class Why {
    public Why(int x, int y) { }
}

How would the deserializer know what to pass when your object is to be deserialized and constructed? He couldn't guess. Thus, the framework requires that serializable objects have to have parameterless constructors, so it is safe to "just create" and it is your responsibility to make whole state settable via properties.

note: by the way - note that the constructor does not have to be public. Most serializers do very well with private parameterless constructors or none at all, if they implemented to use uninitialized object construction, that is available from Reflection in at least the .Net full profile.

Friday, July 30, 2021
 
Akarun
answered 4 Months ago
56

Update:

To provide more information for you.

You don't have an empty Constructor with a string, however you do have String.Empty. The reason is because a string is an immutable object every instance of a string you modify is actually creating a new string in memory.

For instance: string name = ""; though it is an empty string it will still hold around twenty bytes. Where the string.Empty will only hold around four or eight bytes. So though they mean the same thing, one is more efficient than the other.

However I believe you want an empty Constructor to do manipulation that may be more commonly handled by the StringBuilder. Some really nice usage between the two can be found here (Determine performance hit / usage).

Some additional information on the string can be found here. They are immutable thus the contents cannot be changed afterwards.

Example:

string first = "Greg "; // Creates string "first" in memory.
string last = "Arrigotti "; // Creates string "last" in memory.
string name = first + last; // Creates string "name" in memory.

As you edit one of these, it is simply creating a whole new string in memory. If you are looking at a way to potentially handler user data in a field where no middle name exist for instance, the empty string may contain valid usage.

Hopefully these point you in the proper direction.

Sunday, August 15, 2021
 
Nasir
answered 4 Months ago
74

See Attributes that control XML Serialization, e.g.:

[XmlRoot("ChatXMLResult")] 
public class Chat
{
    [XmlElement("Signature")] // optional 
    public string Signature { get; set; }

    [XmlArray]
    [XmlArrayItem(typeof(Message), ElementName="Message")]
    public Message[] Messages { get; set; }
}

public class Message { .. }

etc


Also I see the common element, <Signature />, thus you can introduce a parent class:

public abstract class SignedObject
{
    public string Signature { get; set; }
}
Thursday, August 19, 2021
 
Marcin
answered 4 Months ago
88

It seems it is working as intended. From IgnoreWhitespace documentation:

White space that is not considered to be significant includes spaces, tabs, and blank lines used to set apart the markup for greater readability.

Basically, what it does is preserves (when set to false) whitespaces in between elements such as:

<Foo>

<bar>Text</bar>
</Foo>

The newline between <Foo> and <bar> will be returned by reader. Set IgnoreWhitespace to true, and it won't.

To achieve your goal you'll have to do programmatic trimming, as mentioned by Kirill. When you think about it, how is reader supposed to know whether whitespace of pure string content of element (as in your examples) is just for indenting purposes or actual content?

For more reading on ignoring whitespaces you may want to take a look here and here.

Thursday, September 16, 2021
 
PeanutsMcgee
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share