2010-01-16 2 views
11

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

Глядя на документации, это не говорит о том, что XmlRoot наборы Наследовать ложь с AttributeUsageAttribute (Наследовать предполагаются по умолчанию истины), но я получаю сообщение об ошибке при попытке десериализации моего унаследованного класса без атрибута 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> 

ответ

21

Inherited propertytly просто указывает, что атрибут может унаследовано, не факт, что это будет be. Например, если вы посмотрите на тип подписи для 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 (из рефлектора):

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

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

+1

Тщательный отклик, я ценю фон. Спасибо! –