Как вы сериализуете немодифицируемый класс, который содержит интерфейс?
Я пытаюсь сериализовать объект, который содержит интерфейс. Однако интерфейсы не могут быть сериализованы. Обычно я бы использовал что-то вроде NonSerialized
тег, но я не могу понять, как применить этот атрибут к классу, который я не могу изменить, например, один из предопределенных классов.NET (например: System.Diagnostics.Process
).
Например, рассмотрим следующий код:
using System.Diagnostics
using System.Xml.Serialization;
class Program
{
static void Main(string[] args)
{
try
{
XmlSerializer x = new XmlSerializer(typeof(Process));
}
catch (Exception e)
{
Console.WriteLine(e.InnerException.InnerException.Message);
}
}
}
Это печатает следующий результат:
Cannot serialize member System.ComponentModel.Component.Site of type System.ComponentModel.ISite because it is an interface.
Есть ли способ сделать что-либо из перечисленного ниже в классе, который я не могу изменить, например, системный класс?
- выборочно игнорировать дочерние элементы во время сериализации, так что дочерний элемент вообще не сериализуется
- пометить элемент чем-то, что выполняет то же самое, что и
NonSerialized
Я думал о некоторых решениях, таких как использование отражения для динамической генерации класса, который содержит все те же члены, что и сериализуемый класс, выполнение некоторого типа глубокого копирования и сериализация этого. Тем не менее, мне любопытно посмотреть, есть ли какой-нибудь более простой способ выполнить эту задачу сериализации, кроме перехода к классу, генерирующему маршрут отражения.
2 ответа
Если сериализация существующего типа усложняется, лучшим вариантом всегда будет: создать отдельную модель DTO - которая выглядит примерно так же, как ваша сущность домена, но которая существует только для приятной игры с сериализацией - обычно очень простая (конструкторы без параметров, базовые методы доступа, без проверки и т. д.). Затем карту между ними. В противном случае вы будете играть в игру "бей-моль" с настройкой сериализатора для типа, который ему не очень нравится.
Если вы хотите поиграть в хоккей с XmlSerializer: вы можете создать экземпляр XmlAttributeOverrides, настроить его вручную для вашего конкретного типа (добавив экземпляры атрибута) и передать его в конструктор XmlSerializer. Но это уродливо, довольно неудобно, и вы должны должны кэшировать и повторно использовать экземпляр сериализатора (обычное автоматическое кэширование / повторное использование сборки не применяется, если вы используете эту перегрузку конструктора). Вы можете получить (из экземпляра XmlAttributeOverrides) экземпляр XmlAttributes для каждого типа или члена, а затем при необходимости для свойства XmlIgnore установить значение true. Честно говоря, советую против такого подхода.
Обычно вы сериализуете объект, который вы реализуете сами, что дает вам полный контроль в подобных случаях. Я хотел бы создать объект-оболочку, который реализует ISerializable и в своем конструкторе принимает объект Process. Таким образом, вы можете сами контролировать, какие поля сериализуются.
Сказав это, сериализация исполняемого процесса не представляется жизнеспособной. Я предполагаю, что вы захотите сериализовать объект, который содержит данные строки, которые вы затем используете на другом конце провода (во время десериализации). Класс Process представляет собой работающий экземпляр кода в системе, поэтому кажется странным стремиться его сериализовать.