Как вы сериализуете немодифицируемый класс, который содержит интерфейс?

Я пытаюсь сериализовать объект, который содержит интерфейс. Однако интерфейсы не могут быть сериализованы. Обычно я бы использовал что-то вроде 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.

Есть ли способ сделать что-либо из перечисленного ниже в классе, который я не могу изменить, например, системный класс?

  1. выборочно игнорировать дочерние элементы во время сериализации, так что дочерний элемент вообще не сериализуется
  2. пометить элемент чем-то, что выполняет то же самое, что и NonSerialized

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

2 ответа

Решение

Если сериализация существующего типа усложняется, лучшим вариантом всегда будет: создать отдельную модель DTO - которая выглядит примерно так же, как ваша сущность домена, но которая существует только для приятной игры с сериализацией - обычно очень простая (конструкторы без параметров, базовые методы доступа, без проверки и т. д.). Затем карту между ними. В противном случае вы будете играть в игру "бей-моль" с настройкой сериализатора для типа, который ему не очень нравится.

Если вы хотите поиграть в хоккей с XmlSerializer: вы можете создать экземпляр XmlAttributeOverrides, настроить его вручную для вашего конкретного типа (добавив экземпляры атрибута) и передать его в конструктор XmlSerializer. Но это уродливо, довольно неудобно, и вы должны должны кэшировать и повторно использовать экземпляр сериализатора (обычное автоматическое кэширование / повторное использование сборки не применяется, если вы используете эту перегрузку конструктора). Вы можете получить (из экземпляра XmlAttributeOverrides) экземпляр XmlAttributes для каждого типа или члена, а затем при необходимости для свойства XmlIgnore установить значение true. Честно говоря, советую против такого подхода.

Обычно вы сериализуете объект, который вы реализуете сами, что дает вам полный контроль в подобных случаях. Я хотел бы создать объект-оболочку, который реализует ISerializable и в своем конструкторе принимает объект Process. Таким образом, вы можете сами контролировать, какие поля сериализуются.

Сказав это, сериализация исполняемого процесса не представляется жизнеспособной. Я предполагаю, что вы захотите сериализовать объект, который содержит данные строки, которые вы затем используете на другом конце провода (во время десериализации). Класс Process представляет собой работающий экземпляр кода в системе, поэтому кажется странным стремиться его сериализовать.

Другие вопросы по тегам