Обработка того, как .Net сериализует типы Nullable - PullRequest
4 голосов
/ 20 мая 2011

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

<SomeNode p3:nil="true" xmlns:p3="http://www.w3.org/2001/XMLSchema-instance" />

К сожалению, учитывая, что объектная модель, которую я сериализирую, имеет много-много нулевых значений, я получаю очень большой XML-документ (185 МБ), когда он должен быть намного меньше, а нулевые узлы полностью удалены (20 МБ)

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

Однако это довольно утомительно, так как классы большие, и их много.

Можно ли использовать рефлексию, чтобы упростить процесс добавления ShouldSerialize* методов в класс во время выполнения для всех открытых свойств?

Как я уже писал, я делал это вручную для некоторых классов, и это очень повторяющиеся, сотни функций, которые выглядят так

public bool ShouldSerializeNotes() { return Notes != null; }

Спасибо, -с

Ответы [ 4 ]

2 голосов
/ 25 мая 2011

По аналогии с идеей Марка, но немного более упорядоченной, вы можете вставить все имена классов и свойств в текстовый или XML-файл, а затем использовать его в качестве входных данных для шаблона T4 , который генерирует частичноеклассы с использованием методов ShouldSerialize *.T4 кажется полностью недокументированным в VS2008, но если вы дадите текстовому файлу в своем решении расширение .tt, вам следует настроить правильный инструмент Custom Tool для генерации кода.В VS2010 все поддерживается правильно.

2 голосов
/ 16 декабря 2011

Мое решение: добавьте атрибут к корневому узлу документа следующим образом:

var writer = XmlWriter.Create(...);

writer.WriteStartElement("root");
writer.WriteAttributeString("xmlns", "p3", null, @"http://www.w3.org/2001/XMLSchema-instance");

Тогда XmlSerializer не должен выписывать пространство имен для каждого элемента, допускающего нулевое значение.

2 голосов
/ 21 мая 2011

В качестве одного вы можете просто записать имена свойств в текстовый файл (через type.GetProperties ()) и использовать базовые инструменты (достаточно таблицы), чтобы сгенерировать базовый метод, являющийся свойством. Не сложный, но прагматичный. Конечно, вам необходимо учитывать текущие изменения.

ответить на поставленный вопрос; нет, не совсем (если только вы не внедрили IXmlSerializable, что является проблемой).

Я хотел бы спросить: должен ли это быть XML? Я мог бы сделать так, чтобы и стали намного меньше, если бы вы описали поведение (без данных для нулевых значений), изменив формат данных. Это может быть не вариант, но это кажется излишне большим.

0 голосов
/ 07 мая 2014

В моем случае все переменные / элементы, допускающие значение nullable, имели тип String.Итак, я просто выполнил проверку и присвоил им string.Empty в случае NULL.Таким образом, я избавился от ненужных атрибутов nil и xmlns (p3: nil = "true" xmlns: p3 = "http://www.w3.org/2001/XMLSchema-instance)

// Example:

myNullableStringElement = varCarryingValue ?? string.Empty

// OR

myNullableStringElement = myNullableStringElement ?? string.Empty
...