views:

226

answers:

2

I'm trying to add XML serialization to a fairly trivial class structure in C#. Essentially, there's a single instance of a root class (call it AClass), which holds a List of several instances of some other class (call it AnotherClass):

[XmlRoot("RootNode")]
public class AClass {
    [XmlElement("ListNode")]
    internal List otherObjects { get; set; }
}

public class AnotherClass {
    [XmlAttribute("Name")]
    internal string name { get; set; }
}

When serializing, I'd like for both these classes to be serialized together - that is, if I serialize AClass, its list of AnotherClass gets serialized as well (see this question).

I have this mostly working, but the problem is that during serialization, XmlSerializer only seems to want to deal with public properties of the class - it doesn't serialize AnotherClass at all if the list is declared internal.

I tried making the assembly's internals visible to the serializer:

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Xml")]

That didn't seem to do anything. Is there a way I can get XmlSerializer to recursively serialize lists of objects that are declared internal?

+1  A: 

The idea of adding the InternalsVisibleTo attribute is a good one, but I think that the problem is that the Xml serialization code only looks for the public types in the assembly.
To my knowledge there is no way to make XmlSerializer serialize or deserialize internal types, and you will have to either declare the types as public or write your own serialization code.
Moreover, the XmlSerializer class documentation explicitly states that only public properties of the object will be serialized: "XML serialization is the process of converting an object's public properties and fields to a serial format (in this case, XML) for storage or transport", so it really looks like it's a design decision.

Paolo Tedesco
Actually serializing internal members works fine... (see my answer)
Thomas Levesque
It is possible to serialize internal types with the XmlSerializer, but in that case you will have to write your own custom type serializer by implementing IXmlSerializable on that specific type (and the type itself must be public).
Steven
+5  A: 

You're on the right track... except that the actual serialization is not performed by System.Xml, but by a dynamically generated assembly. You can't predict the name of that assembly (it's randomly generated), so you can't use it in the InternalsVisibleTo attribute.

The only solution is to pre-generate the XML serialization assembly. You can do that using the XML Serializer Generator Tool (Sgen.exe). The name of the generated assembly will be "YourAssembly.XmlSerializers" ; that's the name you have to use in the InternalsVisibleTo attribute.

Thomas Levesque
I didn't know that tool! +1 from me.
Paolo Tedesco
+1 @Thomas: that is good to know. Have you tried this yet yourself?
dboarman
And, btw...great explanation on why `InternalsVisibleTo` attribute will not work in this case!!!
dboarman
Yes I did, and it works fine. Note that it wasn't working in VS2010 beta 1 ; it was a bug, which has been fixed since then
Thomas Levesque