2008-11-06 5 views
146

Я пишу код для сериализации Xml. С функцией ниже.Зачем классу XML-Serializable нужен конструктор без параметров

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 е, булева directReference, булева throwOnError) на System.Xml.Serialization. ModelScope.GetTypeModel (тип тип, Boolean прямая ссылка) на System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping (тип типа, XmlRootAttribute корень, String DefaultNamespace) в System.Xml.Serialization.XmlSerializer..ctor (тип type, String defaultName space) в System.Xml.Serialization.XmlSerializer..ctor (Тип )

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

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

+1

Если вам интересно, я нашел, как создавать объекты без использования конструктора (см. Обновление), но это вообще не поможет XmlSerializer - оно все еще требует этого. Может быть, полезно для пользовательского кода. – 2008-12-24 17:18:28

+0

`XmlSerializer` требует конструктора без параметров по умолчанию для десериализации. – 2015-08-14 13:25:56

ответ

208

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

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

+0

О, так, я могу сделать без параметров ctor частным или внутренним, и сериализация все еще работает. Спасибо за Ваш ответ. – 2008-11-06 05:39:50

0

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

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

65

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

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

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

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

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

Смежные вопросы