2012-05-04 1 views
11

Я столкнулся с некоторым удивительным поведением с использованием XmlSerializer в C#. Рассмотрим следующий фрагмент кода..NET XmlSerializer и вложенные классы в C#

public class A : IEnumerable 
{ 
    public class B 
    { 
     [XmlAttribute] 
     public string PropA { get; set; } 
     [XmlElement] 
     public string PropB { get; set; } 
    } 

    public IEnumerator GetEnumerator() 
    { 
     yield break; 
    } 
} 

class Program 
{ 
    static void Main (string[] args) 
    { 
     XmlSerializer serializer = new XmlSerializer(typeof(A.B)); 

     XmlTextWriter writer = new XmlTextWriter(@"E:\temp\test.xml", Encoding.Default); 
     serializer.Serialize(writer, new A.B() { PropA = "one", PropB = "two" }); 
    } 
} 

В этом примере я стараюсь сериализовать экземпляр вложенного класса A.B, что само по себе не делает использование контейнера класса А в любом случае. Но когда я пытаюсь построить XmlSerializer для него следующее исключение:

InvalidOperationException было необработанное:

Для XML сериализации, типы, которые наследуют от IEnumerable должны реализация Add (System .Object) на всех уровнях их иерархии наследования . Test.A не реализует Add (System.Object).

XmlSerializer пытается применить ограничения сериализации к типу A, когда я на самом деле пытаюсь выполнить сериализацию типа A.B. Однако мое понимание заключается в том, что помимо привилегированного доступа к данным в экземплярах внешнего типа вложенный тип не является особым и ведет себя так, как если бы он находился в пространстве имен.

Неправильно ли это понимание, и ли семантика вложенных типов или XmlSerializer оправдывает это поведение, или это похоже на ошибку в XmlSerializer?

В отношении семантики XmlSerializer существует ли какое-либо документированное требование, которое применяет ограничения XmlSerializer для всех внешних типов при применении к вложенному типу?

+1

У вас нет проблемы с вложенными типами. Ваш класс A не имеет свойства типа 'B'. –

+0

Кроме того, не используйте 'new XmlTextWriter()'. Это было устаревшим с .NET 2.0. Вместо этого используйте 'XmlWriter.Create()'. –

+3

Прошу прощения, но вы полностью упустили мой вопрос. Я не пытаюсь сериализовать A, и я не пытаюсь сериализовать B как свойство A. Я пытаюсь сериализовать его полностью независимо от A. И я знаю о устаревании TextWriter. Это надуманный пример с моей головы, который я старался держать в курсе. –

ответ

0

Это IEnumerable, который создает здесь ограничения. Если вы добавите метод Add, как это было предложено по исключению, ваш код будет работать нормально. Опять же, это мало связано с XmlSerialization и больше с тем, как работает IEnumerable. Пожалуйста, поправьте меня, если я здесь. Проверьте this для хорошего обсуждения на том же самом.

+0

Опять же, я знаю, что такое ограничение, и как его решить. Реальный вопрос: почему это ограничение применяется к типу, который я на самом деле не пытаюсь сериализовать. Другим ограничением, которое, как я заметил, является проблема, является конструктор по умолчанию, хотя мне было сложнее изолировать его на примере. –

+0

Джастин прав. Это ошибка в XML-сериализаторе. Это не та же проблема, что и связанный с вами вопрос. –

0

XmlSerializer предоставляет специальную обработку классам, которые реализуют IEnumerable или ICollection.

более подробно здесь: XmlSerializer and IEnumerable: Serialization possible w/o parameterless constructor: Bug?

+0

Пункт примера, который я представил, состоит в том, что класс, реализующий IEnumerable, фактически не является классом, который сериализуется. Вложенный класс сериализуется и полностью независим. Автор принятого ответа на вопрос, который вы связали, также, похоже, согласен с тем, что это ошибка. –

1

http://msdn.microsoft.com/en-us/library/vstudio/ms229027%28v=vs.100%29.aspx

Поскольку вложенный тип рассматривается в качестве члена объявляющего типа, вложенного типа имеет доступ ко всем остальным членам в объявлении типа.

Поэтому, если сериализатор хочет работать с A.B, ему также требуется определение A. Где IEnumerable пинки проверки в.

Не имеет значения, что В самом деле не относятся к чему-либо в A :)

0

Вероятно, это очень сложная проблема, в сериализации во время выполнения, но я не имеют хорошее объяснение этому поведению. Я чувствую, что ограничение IEnumerable не распространяется на класс B.