8

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?

Filburt
  • 17,626
  • 12
  • 64
  • 115
user377486
  • 693
  • 2
  • 10
  • 19
  • Have you decorated with [Serializable] attribute above your class? – Rajesh Aug 08 '12 at 09:24
  • @Rajesh it wouldn't have serialized *at all* if not... – James Aug 08 '12 at 09:25
  • @James I had the same issue, that he has and when I decorated with serializable it solved the problem. Specially when you are trying to write XMLs. – Rajesh Aug 08 '12 at 09:27
  • 1
    Added [Serializable] before [XmlType] and nothing changed – user377486 Aug 08 '12 at 09:31
  • 2
    `[Serializable]` is required for binary and SOAP serialization, it does not affect XML serialization. – Konrad Morawski Aug 08 '12 at 09:32
  • 3
    This appears to be a known issue with Xml Serialization when dealing with descendants of `List`, see [Xml Serializing List descendant with Xml Attribute](http://stackoverflow.com/questions/3416426/c-sharp-xml-serializing-listt-descendant-with-xml-attribute) – James Aug 08 '12 at 09:37

3 Answers3

4

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; }
}
burning_LEGION
  • 13,246
  • 8
  • 40
  • 52
  • "Cannot serialize member 'Items' of type System.Object. XmlAttribute/XmlText cannot be used to encode complex types." – user377486 Aug 08 '12 at 09:40
  • it's another problem, you avoid it because serializer ignore your element, you must define real type for resolve, f.e. string – burning_LEGION Aug 08 '12 at 09:42
3

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; }
    }
user377486
  • 693
  • 2
  • 10
  • 19
3

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.

Varius
  • 3,197
  • 1
  • 19
  • 8
  • What an annoying edge-case. Why can't XML serialization "just work" for this scenario? Would it be so difficult to automatically, recursively serialize complex classes right down to base data-types? – afarley Jul 02 '19 at 07:47