Почему классу XML-Serializable нужен конструктор без параметров - PullRequest
164 голосов
/ 06 ноября 2008

Я пишу код для сериализации Xml. С функцией ниже.

public static string SerializeToXml(object obj)
{
    XmlSerializer serializer = new XmlSerializer(obj.GetType());
    using (StringWriter writer = new StringWriter())
    {
        serializer.Serialize(writer, obj);
        return writer.ToString();
    }
}

Если аргумент является экземпляром класса без конструктора без параметров, он выдаст исключение.

Необработанное исключение: System.InvalidOperationException: CSharpConsole.Foo не может быть сериализован потому что у него нет конструктор без параметров. в System.Xml.Serialization.TypeDesc.CheckSupported () в System.Xml.Serialization.TypeScope.GetTypeDesc (Тип тип, MemberInfo sourc e, логическое значение directReference, Boolean throwOnError) в System.Xml.Serialization.ModelScope.GetTypeModel (Тип тип, логическая прямая ссылка) в System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping (Тип тип, корень XmlRootAttribute, строка defaultNamespace) в System.Xml.Serialization.XmlSerializer..ctor (Тип тип, String defaultName space) в System.Xml.Serialization.XmlSerializer..ctor (Тип тип)

Почему должен быть конструктор без параметров, чтобы обеспечить успешную сериализацию xml?

РЕДАКТИРОВАТЬ: спасибо за ответ cfeduke. Конструктор без параметров может быть закрытым или внутренним.

Ответы [ 3 ]

231 голосов
/ 06 ноября 2008

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

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

72 голосов
/ 06 ноября 2008

Это ограничение XmlSerializer. Обратите внимание, что BinaryFormatter и DataContractSerializer не требуют этого - они могут создать неинициализированный объект из эфира и инициализировать его во время десериализации.

Поскольку вы используете xml, вы можете рассмотреть возможность использования DataContractSerializer и пометить свой класс [DataContract] / [DataMember], но учтите, что это меняет схему (например, нет эквивалента [XmlAttribute] - все становится элементами).

Обновление: если вы действительно хотите знать, BinaryFormatter и др. Используйте FormatterServices.GetUninitializedObject() для создания объекта без вызова конструктора. Вероятно, опасно; Я не рекомендую использовать его слишком часто ;-p См. Также замечания по MSDN:

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

У меня есть собственный механизм сериализации, но я не собираюсь использовать его FormatterServices; Мне очень нравится знать, что конструктор ( любой конструктор) действительно выполняется.

0 голосов
/ 06 ноября 2008

Прежде всего, это то, что написано в документации . Я думаю, что это одно из ваших полей класса, а не главное - и как вы хотите, чтобы десериализатор построил его обратно без построения без параметров?

Я думаю, что есть обходной путь, чтобы сделать конструктор приватным.

...