11

I have encountered some surprising behavior using XmlSerializer in C#. Consider the following piece of code.

public class A : IEnumerable
{
    public class B
    {
        [XmlAttribute]
        public string PropA { get; set; }
        [XmlElement]
        public string PropB { get; set; }
    }

    public IEnumerator GetEnumerator ()
    {
        yield break;
    }
}

class Program
{
    static void Main (string[] args)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(A.B));

        XmlTextWriter writer = new XmlTextWriter(@"E:\temp\test.xml", Encoding.Default);
        serializer.Serialize(writer, new A.B() { PropA = "one", PropB = "two" });
    }
}

In this example I try to serialize an instance of nested class A.B, which itself doesn't make use of the container class A in any way. But when I attempt to construct the XmlSerializer for it, the following exception is thrown:

InvalidOperationException was unhandled:

To be XML serializable, types which inherit from IEnumerable must have an implementation of Add(System.Object) at all levels of their inheritance hierarchy. Test.A does not implement Add(System.Object).

XmlSerializer is trying to apply serialization constraints against type A when I'm actually trying to serialize type A.B. My understanding however is that aside from privileged access to data in instances of the outer type, a nested type is not special and behaves as if it were in a namespace.

Is this understanding incorrect, and do the semantics of nested types or XmlSerializer justify this behavior, or does this feel like a bug in XmlSerializer?

In specific regard to XmlSerializer semantics, is there any documented requirement that enforces XmlSerializer constraints on all outer types when applied against a nested type?

Justin Aquadro
  • 2,280
  • 3
  • 21
  • 31
  • 1
    You don't have an issue with nested types. Your class A does not have a property of type `B`. – John Saunders May 04 '12 at 02:41
  • Also, don't use `new XmlTextWriter()`. That's been deprecated since .NET 2.0. Use `XmlWriter.Create()` instead. – John Saunders May 04 '12 at 02:43
  • 3
    I'm sorry, but you have missed the point of my question entirely. I am not trying to serialize A, and I am not trying to serialize B as a property of A. I am trying to serialize it completely independent of A. And I am aware of the deprecatedness of TextWriter. This is a contrived example off the top of my head that I've tried to keep brief. – Justin Aquadro May 04 '12 at 02:46
  • 2
    +1 It feels like a bug to me. – phoog May 04 '12 at 05:20

4 Answers4

1

http://msdn.microsoft.com/en-us/library/vstudio/ms229027%28v=vs.100%29.aspx

Because a nested type is treated as a member of the declaring type, the nested type has access to all other members in the declaring type.

So if the serializer wants to work with A.B, it needs the definition of A as well. Where the IEnumerable validation kicks in.

Doesn't matter that B doesn't actually refer to anything in A :)

Vivek
  • 2,103
  • 17
  • 26
0

it is the IEnumerable that is posing the constrains here. If you add the Add method as suggested by the exception, your code will work fine. Again this has little to do with XmlSerialization and more with the way IEnumerable works. Please correct me if I am off here. Check this for a good discussion on the same.

Community
  • 1
  • 1
Codehelp
  • 4,157
  • 9
  • 59
  • 96
  • Again, I know what the constraint is, and how to solve it. The real question is, why is this constraint being applied to a type that I am not actually trying to serialize. The other constraint I've observed being a problem is the default constructor, though I had more difficulty isolating that one by example. – Justin Aquadro May 04 '12 at 12:16
  • Justin is correct. This is a bug in the XML Serializer. This is not the same issue as the question you linked. – John Saunders May 04 '12 at 14:59
0

The XmlSerializer gives special treatment to classes that implement IEnumerable or ICollection.

more details here: XmlSerializer and IEnumerable: Serialization possible w/o parameterless constructor: Bug?

Community
  • 1
  • 1
Ivan Tarapon
  • 219
  • 2
  • 4
  • The point of the example I provided is that the class implementing IEnumerable is not actually the class being serialized. The nested class is being serialized, and is fully independent. The author of the accepted answer of the question you've linked also seems to agree that this is a bug. – Justin Aquadro Mar 07 '13 at 15:30
0

Probably this is a very hard problem in the serialization run-time but i don't have any good explanation to this behavior. I feel like the restriction of IEnumerable don't apply to class B.

Miguel
  • 3,786
  • 2
  • 19
  • 32