Is XmlRootAttribute inheritable?
I have a class I am serializing with C#'s XmlSerializer. It is marked with the XmlRoot attribute, and I would like to inherit this attribut开发者_开发技巧e in a derived class.
Looking at the documentation it does not say that XmlRoot sets Inherit to false with AttributeUsageAttribute (Inherit is supposed to default to true), but I get an error when trying to deserialize my inherited class without an XmlRoot attribute ("<rootNode xmlns=''> was not expected.").
This currently works:
[Serializable()]
[XmlRoot("rootNode")]
public class BaseClass
{
[XmlAttribute("attributeA")]
public int A { get; set; }
}
[Serializable()]
[XmlRoot("rootNode")]
public class InheritedClass : BaseClass
{
[XmlElement("elementB")]
public int B { get; set; }
}
This does not work, but is what I want:
[Serializable()]
[XmlRoot("rootNode")]
public class BaseClass
{
[XmlAttribute("attributeA")]
public int A { get; set; }
}
[Serializable()]
public class InheritedClass : BaseClass
{
[XmlElement("elementB")]
public int B { get; set; }
}
The XML I might try to deserialize as a InheritedClass
looks like this:
<rootNode attributeA="abc">
<elementB>123</elementB>
</rootNode>
The Inherited
propertly merely indicates that the attribute can be inherited, not that it will be. For example, if you look at the type signature for MemberInfo.GetCustomAttributes
, which is the most common way to retrieve these attributes, it has this overload:
public abstract Object[] GetCustomAttributes(bool inherit)
If the parameter inherit
is true
, then the method will search the inheritance chain, i.e. it will look to see if the base class or any ancestor classes have the attribute, if the specific type being looked at does not. In order for this method to find an attribute on an inherited class, the attribute class itself must not set AttributeUsage.Inherited = false
.
However, if the attribute's AttributeUsage.Inherited
is true
, the GetCustomAttributes
method will still ignore it if the inherit
parameter is false
.
In other words, AttributeUsage.Inherited
is a permission, not a requirement. It is completely up to whomever invokes GetCustomAttributes
(or a similar method) to decide whether or not to obtain inherited attributes. You can't control this. I'm fairly certain (not 100% positive) that the XmlSerializer
does not look for inherited attributes.
Maybe not the answer you were looking for, but there you are; looks like you've already figured out the workaround.
Incidentally, the way it works with XML serialization is that the XmlSerializer
uses the XmlReflectionImporter
which in turn gets an instance of XmlAttributes
. Here is what the constructor looks like for XmlAttributes
(out of Reflector):
public XmlAttributes(ICustomAttributeProvider provider)
{
this.xmlElements = new XmlElementAttributes();
this.xmlArrayItems = new XmlArrayItemAttributes();
this.xmlAnyElements = new XmlAnyElementAttributes();
object[] customAttributes = provider.GetCustomAttributes(false);
...
}
So you can see that it does in fact pass false to the GetCustomAttributes
method; it does not look for attributes in base classes, even if those attributes are "inheritable."
精彩评论