Изменения XmlSerializer в .NET 3.5 SP1
-
09-06-2019 - |
Вопрос
Я видел довольно много сообщений об изменениях в .NET 3.5 с пакетом обновления 1 (SP1), но наткнулся на то, что я еще не видел документацию вчера. У меня был код, прекрасно работающий на моей машине, от VS, командной строки msbuild, всего, но на сервере сборки (на .NET 3.5 RTM) произошел сбой.
[XmlRoot("foo")]
public class Foo
{
static void Main()
{
XmlSerializer serializer = new XmlSerializer(typeof(Foo));
string xml = @"<foo name='ack' />";
using (StringReader sr = new StringReader(xml))
{
Foo foo = serializer.Deserialize(sr) as Foo;
}
}
[XmlAttribute("name")]
public string Name { get; set; }
public Foo Bar { get; private set; }
}
В SP1 приведенный выше код работает просто отлично. В RTM вы получаете исключение InvalidOperationException:
Невозможно создать временный класс (результат = 1). Ошибка CS0200: Свойство или индексатор 'ConsoleApplication2.Foo.Bar' нельзя назначить - оно доступно только для чтения
Конечно, все, что нужно для запуска в RTM, - это добавить [XmlIgnore] в свойство Bar.
Мой гугл-фу явно не в состоянии найти документацию о подобных изменениях. Есть ли где-нибудь список изменений, в котором перечислены эти изменения (и подобные скрытые изменения, которые могут появиться и выкрикнуть & Quot; gotcha & Quot;)? Это ошибка или особенность? Р>
EDIT : если в SP1 добавить элемент <Bar />
или установить [XmlElement] для свойства Bar, он не будет десериализован. Он не завершает работу до SP1 при попытке десериализации - он генерирует исключение при создании XmlSerializer.
Это заставляет меня больше склоняться к тому, чтобы это было ошибкой, особенно если я установил атрибут [XmlElement] для Foo.Bar. Если он не может сделать то, что я прошу, он должен генерировать исключение вместо того, чтобы молча игнорировать Foo.Bar. Другие недопустимые комбинации / настройки атрибутов сериализации XML приводят к исключению.
РЕДАКТИРОВАТЬ . Спасибо, ТониБ, я бы не знал о настройке расположения временных файлов. Для тех, кто сталкивается с подобными проблемами в будущем, вам нужен дополнительный флаг настройки:
<system.diagnostics>
<switches>
<add name="XmlSerialization.Compilation" value="1" />
</switches>
</system.diagnostics>
<system.xml.serialization>
<xmlSerializer tempFilesLocation="c:\\foo"/>
</system.xml.serialization>
Даже при установке атрибута [XmlElement] в свойстве Bar его не упоминалось в сгенерированной сборке сериализации, что довольно твердо помещает это в область молчаливо проглоченной ошибки (иначе, ошибка). Либо это, либо дизайнеры решили, что [XmlIgnore] больше не нужен для свойств, которые нельзя установить - и вы ожидаете увидеть это в примечаниях к выпуску, списки изменений или документация XmlIgnoreAttribute .
Решение
В SP1 правильно ли десериализуется свойство foo.Bar?
В до SP1 вы не смогли бы десериализовать объект, потому что метод set свойства Bar является приватным, поэтому у XmlSerializer нет способа установить это значение. Я не уверен, как SP1 справляется с этим.
Вы можете попробовать добавить это в ваш web.config / app.config
<system.xml.serialization>
<xmlSerializer tempFilesLocation="c:\\foo"/>
</system.xml.serialization>
Это поместит класс, сгенерированный XmlSerializer, в c: \ foo, чтобы вы могли видеть, что он делает в SP1 против RTM
Другие советы
Мне скорее нравится это новое (?) поведение, потому что в документе XML нет никакого упоминания о Bar, поэтому десериализатор даже не должен пытаться его установить.