Я пишу код для сериализации 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.ModelS TypeMetTepeTetGet Прямая логическая ссылка) в System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping (Тип тип, корень XmlRootAttribute, String defaultNamespace) в System.Xml.Serialization.XmlSerializer..ctor (Тип тип, пространство String defaultName) в System.Xml.Serialization. XmlSerializer..ctor (Тип тип)
Почему должен существовать конструктор без параметров, чтобы обеспечить успешную сериализацию xml?
РЕДАКТИРОВАТЬ: спасибо за ответ cfeduke. Конструктор без параметров может быть закрытым или внутренним.
источник
XmlSerializer
для десериализации требуется конструктор по умолчанию без параметров.Ответы:
Во время десериализации объекта класс, ответственный за десериализацию объекта, создает экземпляр сериализованного класса, а затем переходит к заполнению сериализованных полей и свойств только после получения экземпляра для заполнения.
Вы можете сделать свой конструктор
private
или,internal
если хотите, просто пока он без параметров.источник
private
илиinternal
все ваши свойства, значения которых были сериализованы, должны иметьpublic
установщики.Это ограничение
XmlSerializer
. Обратите внимание, чтоBinaryFormatter
иDataContractSerializer
не требуют этого - они могут создать неинициализированный объект из эфира и инициализировать его во время десериализации.Поскольку вы используете xml, вы можете подумать об использовании
DataContractSerializer
и пометке вашего класса[DataContract]
/[DataMember
], но обратите внимание, что это меняет схему (например, нет эквивалента[XmlAttribute]
- все становится элементами).Обновление: если вы действительно хотите знать,
BinaryFormatter
и т.д. используйтеFormatterServices.GetUninitializedObject()
для создания объекта, не вызывая конструктор. Вероятно, опасно; Я не рекомендую использовать его слишком часто ;-p См. Также замечания по MSDN:У меня есть собственный движок сериализации, но я не собираюсь его использовать
FormatterServices
; Мне очень нравится знать, что конструктор ( любой конструктор) действительно выполняется.источник
FormatterServices
использовать целую вечностьIXmlSerializable
, но: что происходит после того, как конструктор, и б: это очень некрасиво и трудно получить правильную (особенно десериализацию) - я настоятельно рекомендую пытаться осуществить это, но: это не позволит вам использовать конструкторОтвет таков: без всякой веской причины.
Вопреки своему названию,
XmlSerializer
класс используется не только для сериализации, но и для десериализации. Он выполняет определенные проверки вашего класса, чтобы убедиться, что он будет работать, и некоторые из этих проверок имеют отношение только к десериализации, но в любом случае он выполняет их все, потому что он не знает, что вы собираетесь делать позже.Проверка того, что ваш класс не прошел, является одной из проверок, которые имеют отношение только к десериализации. Вот что происходит:
Во время десериализации
XmlSerializer
класс должен будет создавать экземпляры вашего типа.Чтобы создать экземпляр типа, необходимо вызвать конструктор этого типа.
Если вы не объявили конструктор, компилятор уже предоставил конструктор по умолчанию без параметров, но если вы объявили конструктор, то это единственный доступный конструктор.
Таким образом, если объявленный вами конструктор принимает параметры, то единственный способ создать экземпляр вашего класса - вызвать тот конструктор, который принимает параметры.
Однако
XmlSerializer
он не способен вызывать любой конструктор, кроме конструктора без параметров, поскольку он не знает, какие параметры передавать конструкторам, которые принимают параметры. Таким образом, он проверяет, есть ли в вашем классе конструктор без параметров, и, поскольку он этого не делает, происходит сбой.Итак, если бы
XmlSerializer
класс был написан таким образом, чтобы выполнять только проверки, относящиеся к сериализации, то ваш класс прошел бы, потому что в сериализации нет абсолютно ничего, что требовало бы иметь конструктор без параметров.Как уже отмечали другие, быстрое решение вашей проблемы - просто добавить конструктор без параметров. К сожалению, это также грязное решение, потому что это означает, что вы не можете
readonly
инициализировать какие-либо члены из параметров конструктора.В дополнение ко всему этому,
XmlSerializer
класс мог бы быть написан таким образом, чтобы позволить даже десериализацию классов без конструкторов без параметров. Все, что нужно, это использовать «Шаблон проектирования фабричных методов» (Википедия) . Судя по всему, Microsoft решила, что этот шаблон проектирования слишком сложен для программистов DotNet, которых, очевидно, не следует путать с такими вещами. Таким образом, по мнению Microsoft, программистам DotNet лучше придерживаться конструкторов без параметров.источник
For no good reason whatsoever,
потом,XmlSerializer is not capable of invoking any constructor except a parameterless constructor, because it does not know what parameters to pass to constructors that accept parameters.
если вы не знаете, какие параметры передать конструктору, то как он узнает, какие параметры передать фабрике? Или какую фабрику использовать? Я не могу представить, чтобы этот инструмент был более простым в использовании - вы хотите десериализовать класс, затем позволить десериализатору создать экземпляр по умолчанию, а затем заполнить каждое поле, которое вы пометили. Легко.Прежде всего, это то, что написано в документации . Я думаю, что это одно из ваших полей класса, а не главное - и как вы хотите, чтобы десериализатор построил его обратно без построения без параметров?
Я думаю, что есть обходной путь, чтобы сделать конструктор приватным.
источник