Является ли XmlRootAttribute наследуемым?

У меня есть класс, который я сериализую с С# XmlSerializer. Он отмечен атрибутом XmlRoot, и я хотел бы наследовать этот атрибут в производном классе.

Глядя на документацию, он не говорит, что XmlRoot устанавливает Inherit в false с атрибутом AttributeUsageAttribute (для Inherit по умолчанию используется значение true), но я получаю сообщение об ошибке при попытке десериализации моего унаследованного класса без атрибута XmlRoot ( "< rootNode xmlns = '' > не ожидалось." ).

В настоящее время работает:

[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; }
}

Это не работает, но я хочу:

[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; }
}

XML, который я могу попытаться десериализовать как InheritedClass, выглядит следующим образом:

<rootNode attributeA="abc">
    <elementB>123</elementB>
</rootNode>

Ответ 1

Inherited просто указывает, что атрибут может наследоваться, а не . Например, если вы посмотрите на подпись типа для MemberInfo.GetCustomAttributes, который является наиболее распространенным способом получения этих атрибутов, он имеет эту перегрузку:

public abstract Object[] GetCustomAttributes(bool inherit)

Если параметр inherit равен true, тогда метод будет искать цепочку наследования, то есть он будет смотреть, не имеет ли базовый класс или какие-либо предковые классы атрибут, если на него не просматривается определенный тип, Чтобы этот метод мог найти атрибут в унаследованном классе, сам класс атрибута не должен устанавливать AttributeUsage.Inherited = false.

Однако, если атрибут AttributeUsage.Inherited равен true, метод GetCustomAttributes будет игнорировать его, если параметр inherit false.

Другими словами, AttributeUsage.Inherited является разрешением, а не требованием. Это полностью зависит от того, кто вызывает GetCustomAttributes (или аналогичный метод), чтобы решить, получать или не получать унаследованные атрибуты. Вы не можете контролировать это. Я довольно уверен (не на 100% положительный), что XmlSerializer не ищет унаследованные атрибуты.

Возможно, не ответ, который вы искали, но вот вы; похоже, что вы уже разобрались в обходном пути.

Кстати, способ работы с сериализацией XML состоит в том, что XmlSerializer использует XmlReflectionImporter, который, в свою очередь, получает экземпляр XmlAttributes. Вот как выглядит конструктор для XmlAttributes (из Reflector):

public XmlAttributes(ICustomAttributeProvider provider)
{
    this.xmlElements = new XmlElementAttributes();
    this.xmlArrayItems = new XmlArrayItemAttributes();
    this.xmlAnyElements = new XmlAnyElementAttributes();
    object[] customAttributes = provider.GetCustomAttributes(false);
    ...
}

Итак, вы можете видеть, что он действительно передает false метод GetCustomAttributes; он не ищет атрибуты в базовых классах, даже если эти атрибуты являются "наследуемыми".