user377486
user377486

Reputation: 695

attribute not being serialized by XmlSerializer

I'd like to serialize a class to XML, assigning an XML attribute to it. Snippet:

    [XmlType(TypeName = "classmy")]
    public class MyClass2 : List<object>
    {
        [XmlAttribute(AttributeName = "myattr")]
        public string Name { get; set; }
    }

    public class MyConst
    {
        public MyConst()
        {
            MyClass2 myClass2 = new MyClass2 { 10, "abc" };

            myClass2.Name = "nomm";

            XmlSerializer serializer = new XmlSerializer(typeof(MyClass2));
            serializer.Serialize(Console.Out, myClass2);
        }
    }

But the resulting XML looks like this

<?xml version="1.0" encoding="IBM437"?>
<classmy xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <anyType xsi:type="xsd:int">10</anyType>
  <anyType xsi:type="xsd:string">abc</anyType>
</classmy>

All well and good, with the only exception being that myClass2.Name is not serialized. I was expecting something in the line of

<classmy myattr="nomm" [...]>[...]</classmy>

... Why isn't that serialized, and how can it be?

Upvotes: 8

Views: 10067

Answers (3)

Varius
Varius

Reputation: 3407

XmlSerializer treats List<> in special way:

XmlSerializer can process classes that implement IEnumerable or ICollection differently if they meet certain requirements. A class that implements IEnumerable must implement a public Add method that takes a single parameter. The Add method's parameter must be consistent (polymorphic) with the type returned from the IEnumerator.Current property returned from the GetEnumerator method. A class that implements ICollection in addition to IEnumerable (such as CollectionBase) must have a public Item indexed property (an indexer in C#) that takes an integer, and it must have a public Count property of type integer. The parameter passed to the Add method must be the same type as that returned from the Item property, or one of that type's bases. For classes implementing ICollection, values to be serialized will be retrieved from the indexed Item property rather than by calling GetEnumerator. Also note that public fields and properties will not be serialized, with the exception of public fields that return another collection class (one that implements ICollection). MSDN - scroll to XML Serialization Considerations

That why it serialized Your class as a list of objects only, without Your property. The best solution is to include List as class public property and mark it as XmlElement.

Upvotes: 3

user377486
user377486

Reputation: 695

Alternative solution: use an array instead of a list and XmlElement

    [XmlType(TypeName = "classmy")]
    public class MyClass2
    {
        [XmlElement(ElementName = "Items")]
        public object[] Items { get; set; }
        [XmlAttribute(AttributeName = "myattr")]
        public string Name { get; set; }
    }

Upvotes: 3

burning_LEGION
burning_LEGION

Reputation: 13450

dont derive List<T>, create class with member List

[XmlType(TypeName = "classmy")]
public class MyClass2
{
    [XmlAttribute(AttributeName = "Items")]
    List<object> Items { get; set; } //need to change type in `<>`

    [XmlAttribute(AttributeName = "myattr")]
    public string Name { get; set; }
}

Upvotes: 4

Related Questions