When the XmlSerializer serializes the type, the type itself manages the names of the elements created for its properties. That is, the name of the property becomes the name of the element if it is not statically overridden by XmlElementAttribute.ElementName . XmlTypeAttribute.TypeName usually only manages the name of the element when an instance of the type to which it is applied is not serialized as a property of some containing type - for example, when it is the root element or when it is contained in a collection that is serialized with an external element of the container. This construction avoids name conflicts in cases when a given type has several properties of the same type.
However, in the case of polymorphic property types, there is an exception. For them, the XmlSerializer has the ability to use the XML type name for each of the possible polymorphic types as the name of the element, thereby identifying the actual C # type from which this element was created. To enable this functionality, you need to add several [XmlElement(typeof(TDerived))] attributes to the property, one for each possible type of TDerived .
You can use this feature to generate the required XML by entering the psuedo-polymorphic proxy property:
[XmlType("Outer_X")] public class Outer { public Outer() { this.InnerItem = new Inner(); } [XmlIgnore] public Inner InnerItem { get; set; } [XmlElement(typeof(Inner))] [XmlElement(typeof(object))] [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)] public object InnerItemXmlProxy { get { return InnerItem; } set { InnerItem = (Inner)value; } } }
Then the output will be as you require:
<Outer_X xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Inner_X /> </Outer_X>
Prototype fiddle .
However, as @evk commented, if your Outer class contains several properties of the same type, this cannot be done.
Another possibility to think about: if you just donโt want to manually duplicate name strings of type "Inner_X" in several places (that is, in the attributes [XmlType(string name)] and [XmlElement(string name)] ), you can centralize the type names by making them public const :
[XmlType(Outer.XmlTypeName)] public class Outer { public const string XmlTypeName = "Outer_X"; public Outer() { this.InnerItem = new Inner(); } [XmlElement(Inner.XmlTypeName)] public Inner InnerItem { get; set; } } [XmlType(Inner.XmlTypeName)] public class Inner { public const string XmlTypeName = "Inner_X"; }
Update
I just noticed your comment. I assume that Inner will be an abstract base class, each subclass of which will be serialized for different element names . If so, then the XmlSerializer can indeed be used to use the XML type name as the element name, but only when it can determine statically that the property type is actually polymorphic due to the presence of several attributes [XmlElement(typeof(TDerived))] , Thus, the following classes will generate the required XML:
[XmlType("Outer_X")] public class Outer { public Outer() { this.InnerItem = new InnerX(); } [XmlElement(typeof(InnerX))] [XmlElement(typeof(Inner))]