Снова о сериализаторе

Каждый раз, как я писал об этом своём сериализаторе, я думал, что вот, всё сделано, всё готово… И каждый раз находилось что сделать еще. :) Данный пост не исключение, я снова думаю, что всё сделано. И хотя в основном это понятно (да и интересно) лишь мне, все же опишу, что именно добавилось или поменялось.

Самое главное, я все-таки решил то, на чем остановился в предыдущий раз: сериализации приватных свойств — быть. В итоге, сериализации подлежат следующие поля и свойства:

  • Публичные с полным доступом, без атрибута NotSerialize.
  • Публичные с доступом только на чтение, если они входят в параметры конструктора или их тип является обновляемым, без атрибута NotSerialize.
  • Приватные и защищенные с явно указанным атрибутом Serialize.

Если поле/свойство не проходит ни одно из этих условий, то оно не будет ни сериализовано, ни десериализовано. Библиотека вообще не будет пытаться его обрабатывать.

В целях уменьшения времени начальной инициализации, в конфиг библиотеки был добавлен список сборок, игнорируемых при сканировании типов. По умолчанию в этом списке все основные системные сборки: mscorlib, System, System.Core, System.Xml. Это не значит, что никакие типы из этих сборок не будут сериализоваться. Будут. Просто у тех типов заведомо отсутствуют атрибуты, используемые библиотекой, так зачем их сканировать?

Для клиентского доступа к идентификаторам типов добавлен интерфейс ITypeIdDictionary и метод его получения. В одном месте в Рагиме, вместо собственной проверки на атрибуты TypeId, просто запрашивается этот словарь из библиотеки сериализации. Все равно она просканировала все атрибуты, так почему бы не пользоваться данными?

Добавлена полная поддержка Nullable-типов. Тут, правда, еще пришлось сделать сериализацию null'ов, и пока что оно сделано с помощью xml-атрибута null="true". На будущее наверное стоило бы сделать и xsi-совместимый режим.

И последнее, но пожалуй не менее важное, чем работа с приватными свойствами. Наверное, это вообще самая сложная часть функциональности библиотеки. Я о ссылках, конечно же. Они были весьма переработаны, сперва в целях упрощения — внешние и внутренние ссылки теперь определяются единообразно, одним атрибутом Reference (благодаря чему убавилось чуть ли не на десяток классов). Но затем сюда еще добавилось фича, названная мной «интерфейсные ссылки». Для них добавлен атрибут InterfaceReference, и вся сопутствующая обработка для него.
Хотел описать вкратце, что же это такое, но по мере обдумывания оказалось, что оно будет очень невнятно без полного описания системы ссылок. Скажу лишь результат: свойства, тип которых — интерфейс, но которые являются ссылками, а не вложенными объектами, теперь тоже могут быть сериализованы и обратно.
Нет, это не service locator, как предположил Тиамат, но… На базе внешних ссылок оный локатор вполне легко реализуем. :)

Попозже попробую переписать страницу библиотеки, чтобы было не просто перечисление возможностей (которое уже дважды устарело), а более подробно расписано. А там, вдруг оно станет отправной точкой и для чего-то большего.