Создание сборки сериализации Xml для пользовательского XmlSerializer - PullRequest
2 голосов
/ 07 сентября 2011

В моем классе есть методы для сериализации / десериализации с использованием XML-структуры, отличной от той, которая будет создаваться с сериализатором по умолчанию. Методы создают XmlSerializer для моего типа, но с целой кучей переопределений. Когда эти методы вызываются, я предполагаю, что внутри .NET все еще генерирует сборку сериализации, но я хотел бы сгенерировать эту сборку после компиляции, чтобы она не генерировалась во время выполнения. Как я могу создать сборку сериализации для этой пользовательской сериализации? Если я использую sgen.exe для этого типа, похоже, он генерирует только сериализатор по умолчанию.

В частности, причина, по которой мне нужно сгенерировать сборку сериализации, заключается в том, что мой код вызывается из процесса Internet Explorer, который работает в защищенном режиме. Если среда выполнения .net пытается сгенерировать сборку сериализации, она вызывает csc.exe, и пользователю выдается запрос на разрешение запуска этого процесса. Я не хочу, чтобы пользователи получали подсказки! Поэтому нужно, чтобы вся сериализация / десериализация выполнялась без csc.exe.

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

Возможно, также стоит упомянуть: моя пользовательская сериализация xml также сериализует вложенные классы, так что, возможно, для них тоже будут автоматически сгенерированные сериализаторы. Моя пользовательская сериализация в основном выполняется в соответствии с приведенными ниже инструкциями - она ​​добавляет XmlIgnore к одним свойствам и удаляет XmlIgnore из других. Многие из этих свойств возвращают объекты, которые необходимо сериализовать, некоторые из которых реализуют IXmlSerializable, некоторые используют сериализацию по умолчанию.

    public void SerializeToCustomXml1(XmlWriter writer)
    {
        try
        {
            CustomXmlSerializer1.Serialize(writer, this);
        }
        catch (Exception)
        {
        }
    }

    /// <summary>
    /// Static serializer so it's created just once. There's another one like this CustomXmlSerializer2 with a slightly different format again.
    /// </summary>
    private static XmlSerializer CustomXmlSerializer1
    {
        get
        {
            if (_customXmlSerializer == null)
            {
                XmlAttributes dontIgnore = new XmlAttributes();
                dontIgnore.XmlIgnore = false;

                XmlAttributes attributes;
                XmlAttributeOverrides overrides = new XmlAttributeOverrides();

                // Include some fields in the XML that wouldn't be there otherwise.
                overrides.Add(typeof (WebResource), "ID", dontIgnore);
                overrides.Add(typeof (WebResource), "HasDestinationURLs", dontIgnore);
                overrides.Add(typeof (Resource), "AccessDefindBy", dontIgnore);

                attributes = new XmlAttributes();
                attributes.XmlIgnore = false;
                attributes.XmlElements.Add(new XmlElementAttribute("ActionID"));
                overrides.Add(typeof(Action), "ID", attributes);

                // Instead of serializing the Actions field we serialize CustomActionsXmlSerializer,
                // which outputs different content in the XML
                overrides.Add(typeof (WebResource), "Actions", ignore);
                attributes = new XmlAttributes();
                attributes.XmlIgnore = false;
                attributes.XmlElements.Add(new XmlElementAttribute("Actions"));
                overrides.Add(typeof (WebResource), "CustomActionsXmlSerializer", attributes);                  

                // ... more of these overrides here ... 
                _customXmlSerializer1 = new XmlSerializer(typeof(WebResource), overrides);
            }
            return _customXmlSerializer1;
        }

Кросс-пост здесь и здесь .

UPDATE: О, этот ответ предполагает, что это просто невозможно, поскольку XmlSerializer даже не ищет предварительно скомпилированную сборку, если вы используете XmlOverrides. Штопать. Тогда я думаю, что мой лучший вариант - сгенерировать код сериализации и включить его в мой проект и вызывать его напрямую вместо вызова XmlSerializer. Есть мысли о том, как сделать это аккуратно?

Ответы [ 2 ]

2 голосов
/ 08 сентября 2011

Если вы под "пользовательским XmlSerializer" подразумеваете, что вы используете System.Xml.XmlSerializer с пользовательским кодом сериализации (через атрибуты IXmlSerializable или [XmlElement] и друзья), он должен искать сборку под названием MyAssembly.XmlSerializers.dll при сериализации.

Наименование сборки важно, и если вы не уверены, ищется ли она и какое именно имя сборки ищется, вы можете просто прикрепить обработчик события к AppDomain.CurrentDomain.FirstChanceException, который сработает для всех исключений в домене приложения, включая исключения загрузки сборок. Вы также можете подключиться к событиям AppDomain.CurrentDomain.AssemblyLoad и AppDomain.CurrentDomain.AssemblyResolve, которые должны запускаться каждый раз при первой загрузке сборки в домен приложения.

Другая важная вещь заключается в том, что версии (и, возможно, ключевые; я не уверен) MyAssembly.dll и MyAssembly.XmlSerializers.dll должны совпадать, и они также должны располагаться рядом друг с другом. См. это и эту статью MSDN для получения дополнительной информации.

0 голосов
/ 16 сентября 2011

(пока недостаточно комментариев для комментирования)

Вам следует подумать над тем, чтобы укусить маркер и реализовать IXmlSerializable таким образом, который позволяет вам решать, что сериализировать, а что нет, не изменяя атрибуты во время выполнения.Определите свои собственные атрибуты, требования конструктора и сериализуйте их.

Возможно, вы могли бы даже отказаться от XML-сериализации и переключиться на JSon.Net, где необходимость перепрыгивать через такие скачки весьма маловероятна.

...