Порядок выполнения кода XML-сериализации в конструкторе - как это изменить? - PullRequest
1 голос
/ 03 октября 2011

Я сериализирую XML-файл в объект, используя встроенную функциональность .NET (XmlSerializer.Deserialize).После того, как поля объекта были установлены, я хочу воздействовать на эти данные, вызывая дополнительный код в конструкторе объекта.К сожалению, пошаговое выполнение кода показывает, что «дополнительный» код выполняется в первую очередь перед выполнением логики сериализации.Это делает такой подход неосуществимым, поскольку поля еще не были инициализированы, и нет данных для обработки.

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

Ответы [ 3 ]

4 голосов
/ 03 октября 2011

Если вызывается конструктор, он всегда будет first (обратите внимание, что некоторые сериализаторы пропускают конструктор; XmlSerializer всегда запускает открытый конструктор без параметров). Таким образом, любая логика должна быть в свойствах и т. Д.

То, что вы действительно описываете здесь, это "обратный вызов сериализации" - то есть способ заставить ваш сериализатор запустить ваш метод до и / или после сериализации и / или десериализации; некоторые сериализаторы поддерживают обратные вызовы - однако XmlSerializer не .

Единственный вариант с XmlSerializer - реализовать IXmlSerializable, но, честно говоря, это огромная боль. Если возможно, я бы предложил либо:

  • вызов метода вручную, самостоятельно, после десериализации
  • или переключите сериализатор на тот, который поддерживает обратные вызовы

DataContractSerializer поддерживает обратные вызовы и может делать limited xml - не такой детальный контроль, как XmlSerializer, хотя (без атрибутов , в частности); Protobuf-net поддерживает обратные вызовы, если вы хотите переключиться на двоичный файл.

1 голос
/ 03 октября 2011

Предполагая, что вы не реализовали IXmlSerializable, сериализатор следует этой последовательности для десериализации:

  • Создание экземпляра вашего объекта
  • Считывание XML по частям
  • Установите свойства для вашего объекта

Сериализатор не может получить доступ к свойствам объекта до завершения строительства, поэтому нет способа сделать то, что вы хотите сделать. Редактировать: Даже если вы пропустите конструктор (см. Комментарии к ответу Марка), вы не сможете вызвать конструктор после установки свойств объекта, поскольку вы не можете вызвать конструкторбез создания нового объекта.

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

0 голосов
/ 03 октября 2011

В прошлом я занимался созданием метода десериализации для объекта, который вы создаете. Это включает в себя всю логику сериализации в одном месте с возможностью добавления пользовательского кода до и / или после сериализации.

Примерно так:

public partial class MyObject
{
    public static MyObject Deserialize(string xmlInputFile)
    {
        MyObject myobject;

        //INSERT CODE HERE THAT RUNS BEFORE DESERIALIZATION

        using (StreamReader sr = new StreamReader(xmlInputFile))
        {
            XmlSerializer xs = new XmlSerializer(typeof (MyObject));
            myobject = (MyObject) xs.Deserialize(sr);
            sr.Close();
        }

        //INSERT CODE HERE THAT RUNS AFTER DESERIALIZATION

        return myobject;
    }
}

Десериализация файла XML в новый объект так же проста, как запись:

MyObject myobject = MyObject.Deserialize(PathToXMLFile);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...