Является ли XmlRootAttribute наследуемым? - PullRequest
12 голосов
/ 16 января 2010

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

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

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

[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 Ответ

24 голосов
/ 16 января 2010

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; не ищет атрибуты в базовых классах, даже если эти атрибуты являются «наследуемыми».

...