Сериализация и восстановление неизвестного класса

var button = document.querySelector("input[type=button]");
button.addEventListener("click", function() {
  alert("button was clicked");
})
11
задан John Saunders 6 December 2011 в 17:17
поделиться

7 ответов

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

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
static class Program
{
    static readonly XmlSerializer ser;
    static Program()
    {
        List<Type> extraTypes = new List<Type>();
        // TODO: read config, or use reflection to
        // look at all assemblies
        extraTypes.Add(typeof(Bar));
        ser = new XmlSerializer(typeof(Foo), extraTypes.ToArray());
    }
    static void Main()
    {
        Foo foo = new Bar();
        MemoryStream ms = new MemoryStream();
        ser.Serialize(ms, foo);
        ms.Position = 0;
        Foo clone = (Foo)ser.Deserialize(ms);
        Console.WriteLine(clone.GetType());
    }
}

public abstract class Foo { }
public class Bar : Foo {}
9
ответ дан 3 December 2019 в 07:14
поделиться

Вы не должны помещать функции сериализации ни в какой базовый класс, вместо этого, можно добавить его к Служебному Классу.

например, (код, например, только, rootName является дополнительным),

public static class Utility
{
       public static void ToXml<T>(T src, string rootName, string fileName) where T : class, new()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T), new XmlRootAttribute(rootName));
            XmlTextWriter writer = new XmlTextWriter(fileName, Encoding.UTF8);
            serializer.Serialize(writer, src);
            writer.Flush();
            writer.Close();
        }
}

Просто выполните вызов к

Utility.ToXml( fooObj, "Foo", @"c:\foo.xml");

Не только типы семейства Foo могут использовать его, но и все другие сериализуемые объекты.

Править

Хорошо полный сервис... (rootName является дополнительным),

public static T FromXml<T>(T src, string rootName, string fileName) where T : class, new()
{
    XmlSerializer serializer = new XmlSerializer(typeof(T), new XmlRootAttribute(rootName));
    TextReader reader = new StreamReader(fileName);
    return serializer.Deserialize(reader) as T;
}
3
ответ дан 3 December 2019 в 07:14
поделиться

Хорошо сериализация не должна быть проблемой, конструктор XmlSerializer берет Аргумент типа, даже называние GetType на экземпляре производного класса через метод на абстрактной основе возвратит производные типы фактический Тип. Так же в сущности, пока Вы знаете надлежащий тип после десериализации затем, сериализация надлежащего типа тривиальна. Таким образом, можно реализовать метод на названной основе, сериализируют или что имеет Вас, который передает this.GetType() конструктору XmlSerializer.. или просто раздает текущую ссылку и позволяет сериализировать методу заботиться о нем, и необходимо быть в порядке.

Править: Обновление для редактирования OP..

Если Вы не знаете тип при десериализации затем, у Вас действительно есть только массив строк или массив байтов, без своего рода идентификатора где-нибудь Вы - отчасти ручей. Существуют некоторые вещи, которые можно сделать как попытка десериализовать как каждый известный производный тип xx базового класса, я не рекомендовал бы это.

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

2
ответ дан 3 December 2019 в 07:14
поделиться

Где-нибудь глубоко в пространствах имен XML находится замечательный класс под названием XmlReflectionImporter.

Это может помочь Вам, если необходимо создать схему во времени выполнения.

1
ответ дан 3 December 2019 в 07:14
поделиться

Можно также сделать это путем создания XmlSerializer passign во всех возможных типах конструктору. Предупредите, что при использовании этого конструктора, xmlSerializer будет скомпилирован каждый раз и приведет к утечке при постоянном воссоздании его. Вы захотите создать единственный сериализатор и снова использовать его в Вашем приложении.

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

1
ответ дан 3 December 2019 в 07:14
поделиться

Эти ссылки, вероятно, будут полезны Вам:

У меня есть сложный проект дистанционной работы и требуемый очень жесткий контроль над сериализированным XML. Сервер мог получить объекты, что он понятия не имел, как десериализовать и наоборот, таким образом, мне был нужен способ определить их быстро.

Все решения.NET, которые я попробовал, испытали недостаток в необходимой гибкости моего проекта.

Я храню международный атрибут в основе xml для идентификации типа объекта.

Если я должен создать новый объект из xml, я создал класс фабрики, который проверяет, что атрибут типа затем создает соответствующий производный класс и подает его xml.

Я сделал что-то вроде этого (вытаскивающий это из памяти, таким образом, синтаксис может быть немного выключен):

(1) Созданный интерфейс

interface ISerialize
{
    string ToXml();
    void FromXml(string xml);       
};

(2) Базовый класс

public class Base : ISerialize
{
    public enum Type
    {
        Base,
        Derived
    };

    public Type m_type;

    public Base()
    {
        m_type = Type.Base;
    }

    public virtual string ToXml()
    {
        string xml;
        // Serialize class Base to XML
        return string;
     }

    public virtual void FromXml(string xml)
    {
        // Update object Base from xml
    }
};

(3) Производный класс

public class Derived : Base, ISerialize
{
    public Derived()
    {
         m_type = Type.Derived;
    }

    public override virtual string ToXml()
    {
        string xml;
        // Serialize class Base to XML
        xml = base.ToXml();
        // Now serialize Derived to XML
        return string;
     }
     public override virtual void FromXml(string xml)
     {
         // Update object Base from xml
         base.FromXml(xml);
         // Update Derived from xml
     }
};

(4) Объектная фабрика

public ObjectFactory
{
    public static Base Create(string xml)
    {
        Base o = null;

        Base.Type t;

        // Extract Base.Type from xml

        switch(t)
        {
            case Base.Type.Derived:
                o = new Derived();
                o.FromXml(xml);
            break;
         }

        return o;
    }
};
1
ответ дан 3 December 2019 в 07:14
поделиться

Отмечание классов как сериализуемые и использование SoapBinaryFormatter вместо XmlSerializer дадут Вам эту функциональность автоматически. Когда сериализация информации о типе сериализируемого экземпляра будет записана в XML, и SoapBinaryFormatter может инстанцировать подклассов при десериализации.

0
ответ дан 3 December 2019 в 07:14
поделиться
Другие вопросы по тегам:

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