Почему классу XML-Serializable нужен конструктор без параметров

Я пишу код для сериализации 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(Тип type, MemberInfo sourc e, Boolean directReference, Boolean throwOnError) в System.Xml.Serialization.ModelScope.GetTypeModel(Тип type, Boolean direct Reference) в System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Тип type, XmlRootAttribute root, String defaultNamespace) в System.Xml.Serialization.XmlSerializer..ctor(Тип type, String defaultName) на System.Xml.Serialization.XmlSerializer..ctor(Тип тип)

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

EDIT: спасибо за ответ cfeduke. Конструктор без параметров может быть закрытым или внутренним.

Ответ 1

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

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

Ответ 2

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

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

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

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

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

Ответ 3

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

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