Сериализация XML и наследованные типы

Для выбора только определенных столбцов из нескольких столбцов для заданного значения в pandas:

select col_name1, col_name2 from table where column_name = some_value.

Опции:

df.loc[df['column_name'] == some_value][[col_name1, col_name2]]

или

df.query['column_name' == 'some_value'][[col_name1, col_name2]]
84
задан Community 23 May 2017 в 12:00
поделиться

6 ответов

Проблема решена!

Хорошо, так что я, наконец, добрался до цели (правда, с помощью партии помощи от здесь !).

Итак, резюмируйте:

Цели:

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

Выявленные проблемы / Примечания:

  • XmlSerializer делает довольно интересное отражение, но он очень ограничен, когда дело доходит до абстрактных типов (то есть он будет работать только с экземплярами самого абстрактного типа, а не с подклассами).
  • Декораторы атрибутов Xml определяют, как XmlSerializer обрабатывает свойства своих находит. Физический тип также можно указать, но это создает тесную связь между классом и сериализатором (не очень хорошо).
  • Мы можем реализовать наш собственный XmlSerializer, создав класс, реализующий IXmlSerializable .

Решение

Я создал универсальный класс, в котором вы указываете универсальный тип как абстрактный тип, с которым вы будете работать. Это дает классу возможность «переводить» между абстрактным типом и конкретным типом, поскольку мы можем жестко запрограммировать приведение типов (т.е. мы можем получить больше информации, чем может XmlSerializer).

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

Поскольку XmlSerializer не может выполнять приведение, нам нужно предоставить код для этого, поэтому неявный оператор затем перегружается (я даже не знал, что вы можете сделать это!).

Код для AbstractXmlSerializer следующий:

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;

namespace Utility.Xml
{
    public class AbstractXmlSerializer<AbstractType> : IXmlSerializable
    {
        // Override the Implicit Conversions Since the XmlSerializer
        // Casts to/from the required types implicitly.
        public static implicit operator AbstractType(AbstractXmlSerializer<AbstractType> o)
        {
            return o.Data;
        }

        public static implicit operator AbstractXmlSerializer<AbstractType>(AbstractType o)
        {
            return o == null ? null : new AbstractXmlSerializer<AbstractType>(o);
        }

        private AbstractType _data;
        /// <summary>
        /// [Concrete] Data to be stored/is stored as XML.
        /// </summary>
        public AbstractType Data
        {
            get { return _data; }
            set { _data = value; }
        }

        /// <summary>
        /// **DO NOT USE** This is only added to enable XML Serialization.
        /// </summary>
        /// <remarks>DO NOT USE THIS CONSTRUCTOR</remarks>
        public AbstractXmlSerializer()
        {
            // Default Ctor (Required for Xml Serialization - DO NOT USE)
        }

        /// <summary>
        /// Initialises the Serializer to work with the given data.
        /// </summary>
        /// <param name="data">Concrete Object of the AbstractType Specified.</param>
        public AbstractXmlSerializer(AbstractType data)
        {
            _data = data;
        }

        #region IXmlSerializable Members

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null; // this is fine as schema is unknown.
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            // Cast the Data back from the Abstract Type.
            string typeAttrib = reader.GetAttribute("type");

            // Ensure the Type was Specified
            if (typeAttrib == null)
                throw new ArgumentNullException("Unable to Read Xml Data for Abstract Type '" + typeof(AbstractType).Name +
                    "' because no 'type' attribute was specified in the XML.");

            Type type = Type.GetType(typeAttrib);

            // Check the Type is Found.
            if (type == null)
                throw new InvalidCastException("Unable to Read Xml Data for Abstract Type '" + typeof(AbstractType).Name +
                    "' because the type specified in the XML was not found.");

            // Check the Type is a Subclass of the AbstractType.
            if (!type.IsSubclassOf(typeof(AbstractType)))
                throw new InvalidCastException("Unable to Read Xml Data for Abstract Type '" + typeof(AbstractType).Name +
                    "' because the Type specified in the XML differs ('" + type.Name + "').");

            // Read the Data, Deserializing based on the (now known) concrete type.
            reader.ReadStartElement();
            this.Data = (AbstractType)new
                XmlSerializer(type).Deserialize(reader);
            reader.ReadEndElement();
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            // Write the Type Name to the XML Element as an Attrib and Serialize
            Type type = _data.GetType();

            // BugFix: Assembly must be FQN since Types can/are external to current.
            writer.WriteAttributeString("type", type.AssemblyQualifiedName);
            new XmlSerializer(type).Serialize(writer, _data);
        }

        #endregion
    }
}

Итак, откуда мы можем сказать XmlSerializer работать с нашим сериализатором, а не с сериализатором по умолчанию? Мы должны передать наш тип в свойстве типа атрибутов Xml, например:

[XmlRoot("ClassWithAbstractCollection")]
public class ClassWithAbstractCollection
{
    private List<AbstractType> _list;
    [XmlArray("ListItems")]
    [XmlArrayItem("ListItem", Type = typeof(AbstractXmlSerializer<AbstractType>))]
    public List<AbstractType> List
    {
        get { return _list; }
        set { _list = value; }
    }

    private AbstractType _prop;
    [XmlElement("MyProperty", Type=typeof(AbstractXmlSerializer<AbstractType>))]
    public AbstractType MyProperty
    {
        get { return _prop; }
        set { _prop = value; }
    }

    public ClassWithAbstractCollection()
    {
        _list = new List<AbstractType>();
    }
}

Здесь вы можете видеть, что у нас есть коллекция и одно свойство, и все, что нам нужно сделать, это добавить именованный параметр type в объявление Xml, просто! : D

ПРИМЕЧАНИЕ: Если вы используете этот код, я был бы очень признателен за внимание. Это также поможет привлечь больше людей в сообщество :)

Теперь, но не уверен, что делать с ответами здесь, так как у всех были свои за и против. Я модифицирую те, которые, по моему мнению, были полезны (без обид на тех, кто не был), и закрываю это, как только у меня будет представитель:)

Интересная проблема и хорошее развлечение! :)

Я был бы очень признателен за крик. Это также поможет привлечь больше людей в сообщество :)

Теперь, но не уверен, что делать с ответами здесь, так как у всех были свои за и против. Я модифицирую те, которые, по моему мнению, были полезны (без обид на тех, кто не был), и закрываю это, как только у меня будет представитель:)

Интересная проблема и хорошее развлечение! :)

Я был бы очень признателен за крик. Это также поможет привлечь больше людей в сообщество :)

Теперь, но не уверен, что делать с ответами здесь, так как у всех были свои за и против. Я модифицирую те, которые, по моему мнению, были полезны (без обид на тех, кто не был), и закрываю это, как только у меня будет представитель:)

Интересная проблема и хорошее развлечение! :)

54
ответ дан 24 November 2019 в 08:39
поделиться

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

Конструктор XmlSerialiser с РЕДАКТИРОВАНИЕМ extraTypes param

: Я добавил бы, что этот подход обладает преимуществом по атрибутам XmlInclude и т.д., что можно разработать способ обнаружить и составить список возможных конкретных типов во времени выполнения и наполнить их в.

9
ответ дан Shaun Austin 24 November 2019 в 08:39
поделиться

Серьезно, расширяемая платформа POCOs никогда не будет сериализировать к XML надежно. Я говорю это, потому что я могу гарантировать, что кто-то приедет, расширит Ваш класс и испортит его.

необходимо изучить использование XAML для сериализации графов объектов. Это разработано, чтобы сделать это, тогда как сериализация XML не.

сериализатор Xaml и deserializer обрабатывают дженерики без проблемы, наборов базовых классов и интерфейсов также (как долго, поскольку сами наборы реализуют IList или IDictionary). Существуют некоторые протесты, такие как маркировка Ваших свойств набора только для чтения с эти DesignerSerializationAttribute, но переделка Вашего кода для обработки этих угловых случаев не является этим трудно.

3
ответ дан 24 November 2019 в 08:39
поделиться

Просто быстрое обновление на этом, я не забыл!

Просто выполнение еще некоторого исследования, похож, я иду победителю, просто должны были отсортировать код.

До сих пор, у меня есть следующее:

  • XmlSeralizer является в основном классом, который делает некоторое изящное отражение о классах, которые это сериализирует. Это определяет свойства, которые сериализируются на основе Тип .
  • причина, проблема происходит, то, потому что несоответствие типов происходит, это ожидает BaseType, но на самом деле получает DerivedType.. В то время как можно думать, что это рассматривало бы его полиморфно, это не делает, так как это включило бы целую дополнительную загрузку отражения и проверки типа, которую это не разработано, чтобы сделать.

Это поведение, кажется, в состоянии быть переопределенным (ожидание кода) путем создания прокси-класса для действия как посредник для сериализатора. Это в основном определит тип производного класса и затем сериализирует это как нормальное. Этот прокси-класс тогда подаст это, XML создают резервную копию строки к основному сериализатору..

Часы это пространство! ^_^

2
ответ дан Rob Cooper 24 November 2019 в 08:39
поделиться

Это - конечно, решение Вашей проблемы, но существует другая проблема, которая несколько подрывает Ваше намерение использовать "портативный" формат XML. Плохая вещь происходит, когда Вы решаете изменить классы в следующей версии Вашей программы, и необходимо поддерживать оба формата сериализации - новая и старая (потому что клиенты все еще используют свои старые файлы/базы данных, или они соединяются с сервером с помощью старой версии продукта). Но Вы не можете больше использовать этот serializator, потому что Вы использовали

type.AssemblyQualifiedName

, который похож

TopNamespace.SubNameSpace.ContainingClass+NestedClass, MyAssembly, Version=1.3.0.0, Culture=neutral, PublicKeyToken=b17a5c561934e089

, который является, содержит Ваши атрибуты сборки и версию...

Теперь, при попытке изменить свою версию блока, или Вы решаете подписать ее, эта десериализация не собирается работать...

2
ответ дан Max Galkin 24 November 2019 в 08:39
поделиться

Я сделал вещи, подобные этому. То, что я обычно делаю, удостоверяются, что все атрибуты сериализации XML находятся на реальном классе, и просто имеют свойства на том вызове класса до базовых классов (при необходимости) для получения информации, которая будет de/serialized, когда сериализатор обратится к тем свойствам. Это немного больше кодирует работу, но это действительно работает намного лучше, чем попытка вынудить сериализатор просто сделать правильную вещь.

1
ответ дан TheSmurf 24 November 2019 в 08:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: