Страницы

Поиск по вопросам

Показаны сообщения с ярлыком serializable. Показать все сообщения
Показаны сообщения с ярлыком serializable. Показать все сообщения

пятница, 24 января 2020 г.

Deserialize вариационных (типизированных) XML

#c_sharp #xml #serializable #unserialize


Раньше не сталкивался с сериализацией объектов, особенно с сериализацией в XML и
обратно, но пришлось - да не знаю как быть с объектами в которых присутствует поле
класса Object, в котором могут быть объекты нескольких типов.

Пример XML:

  
  
    
      123
      1001
    
    
      232
      1001
    
    
      943
      TheName
    
  


Пример XML:

  
    Error Message
  
  


Предполагаю, что классы можно записать так (хотя в записи не уверен, ибо не работает):
[XmlRootAttribute("Entities", Namespace = "http://site.org/", IsNullable = false)]
public class BoxPackages {
  [XmlArray(IsNullable = true)]
  public BoxError Error;
  [XmlArray(IsNullable = true)]
  public object[] Package;
}

public class BoxError {
    public String Message;
}

[XmlRootAttribute("TypeA")]
public class PackageTypeA {
  public Int32 ID;
  public Int64 Number;
}

[XmlRootAttribute("TypeB")]
public class PackageTypeB {
  public Int32 ID;
  public Byte Type;
}

[XmlRootAttribute("TypeC")]
public class PackageTypeC {
  public Int32 ID;
  public String Name;
}

Понятно, что классов не достаточно - нужна ещё какая-то настройка сериализатора.
Кто знает, как настроить сериализатор (XmlAttributes из коробки) для десериализации
XML в объект типа BoxPackages? Подскажите, пожалуйста?    


Ответы

Ответ 1



Класс XmlSerializer умеет сериализовать только известные типы. Т.к. в массве object[] может быть любой объект любого типа, в конструкторе этого класса надо перечислить все возможные типы объектов, которые предполагается использовать: Type [] extraTypes = new Type[3]; extraTypes[0] = typeof(PackageTypeA); extraTypes[1] = typeof(PackageTypeB); extraTypes[2] = typeof(PackageTypeC); // Create the XmlSerializer instance. XmlSerializer mySerializer = new XmlSerializer(typeof(BoxPackages),extraTypes); Этот пример основан на XmlSerializer - конструктор.

вторник, 31 декабря 2019 г.

Сериализация в С++

#cpp #json #xml #ооп #serializable


Прошу дать ссылки, или, если есть желание, рассказать вкратце о красивом, удобном
способе сериализации полей класса в C++. Приведу пример (не уверен, что так можно,
но хотелось бы) - использовать свойства, аналогичные свойствам в C#, перед полями,
которые будут учавствовать в сериализации (но: рефлексия ?), все автоматически упаковывается
в JSON/XML (если это важно, то JSON меня интересует в большей степени), аналогично
читается из JSON/XML и инициализирует соостветствующие поля объекта.
    


Ответы

Ответ 1



Универсального решения нет - и быть не может без рефлексии - которая будет - возможно - только в следующих версиях плюсов - да и с ней - если будут накладные расходы - универсального решения не будет. Вы можете выбирать из библиотек. По скорости или удобству использования. "свойства, аналогичные свойствам в C#, перед полями" реализуются всеми этими либами через макросы (слегка приврал), многое из того, что раньше можно было достичь только макросами сейчас можно достижимо средствами шаблонов C++, но: вот пример использования boost::serialization c макросами. Пример добавления рефлексии с шаблонами и макросами. RTTI с макросами Сами по себе макросы - зло, но бывают и необходимым злом. я для себя взял rapidjson (пушо очень быстрая) и сделал вокруг нее пару обвязок типа stringValue / intValue. В принципе, достаточно удобно пока. По поводу бустов: попользуйтесь, наверняка будет полезно. Выпиливать куски не надо, на рантайм это не повлияет, может быть только на время компиляции. Если подойдет другая либа для json/xml (POCO) например, берите ту, что вам удобнее в использовании. Вам главное инкапсулировать как можно больше, чтобы вы могли сменить потом либу, а не ловить ее вызовы по всему коду

Как пометить класс как [Serializable] ,если он подгружается из dll

#c_sharp #сериализация #serializable


Я использую dll файлы в моем проекте. Как пометить класс как сериализуемый атрибутом
[serializable].
Я не имею исходного кода, только dll файл, на который есть ссылка в моем классе.
Я хочу сделать его сериализуемым, чтобы использовать состояние представления для
моего объекта, который использует dll. Использую бинарную сериализацию.
Как решить проблему?
    


Ответы

Ответ 1



Если вы можете вручную, кодом, извлечь из такого объекта все нужные свойства, то можно использовать механизм Surrogate Selector. Код честно взят из MSDN. Employee - тот самый "внешний" класс, на который нельзя поставить [Serializable]: using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Serialization.Formatters.Binary; // This class is not serializable. class Employee { public String name, address; public Employee(String name, String address) { this.name = name; this.address = address; } } // This class can manually serialize an Employee object. sealed class EmployeeSerializationSurrogate : ISerializationSurrogate { // Serialize the Employee object to save the object's name and address fields. public void GetObjectData(Object obj, SerializationInfo info, StreamingContext context) { Employee emp = (Employee) obj; info.AddValue("name", emp.name); info.AddValue("address", emp.address); } // Deserialize the Employee object to set the object's name and address fields. public Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) { Employee emp = (Employee) obj; emp.name = info.GetString("name"); emp.address = info.GetString("address"); return null; } } public sealed class App { static void Main() { // This sample uses the BinaryFormatter. IFormatter formatter = new BinaryFormatter(); // Create a MemoryStream that the object will be serialized into and deserialized from. using (Stream stream = new MemoryStream()) { // Create a SurrogateSelector. SurrogateSelector ss = new SurrogateSelector(); // Tell the SurrogateSelector that Employee objects are serialized and deserialized // using the EmployeeSerializationSurrogate object. ss.AddSurrogate(typeof(Employee), new StreamingContext(StreamingContextStates.All), new EmployeeSerializationSurrogate()); // Associate the SurrogateSelector with the BinaryFormatter. formatter.SurrogateSelector = ss; try { // Serialize an Employee object into the memory stream. formatter.Serialize(stream, new Employee("Jeff", "1 Microsoft Way")); } catch (SerializationException e) { Console.WriteLine("Serialization failed: {0}", e.Message); throw; } // Rewind the MemoryStream. stream.Position = 0; try { // Deserialize the Employee object from the memory stream. Employee emp = (Employee) formatter.Deserialize(stream); // Verify that it all worked. Console.WriteLine("Name = {0}, Address = {1}", emp.name, emp.address); } catch (SerializationException e) { Console.WriteLine("Deserialization failed: {0}", e.Message); throw; } } } } // This code produces the following output. // // Name = Jeff, Address = 1 Microsoft Way т.е. сериализоваться будет класс без аттрибута [Serializable], но как именно его сериализовать - вам придется описать самому.

Ответ 2



Атрибуты класса лежат в метаданных, которые лежат внутри скомпилированной сборки, то есть пометить класс как [Serializable] у вас не получится. Пользуйтесь сериализатором, который не смотрит на эти аттрибуты.

пятница, 27 декабря 2019 г.

Как сериализовать/десериализовать объект который содержит другой объект?

#java #serializable #classloader


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

Например, класс Foo с Bar объектом внутри.

class Foo implements Serializable {
    Bar bar;
}


Класс Bar

class Bar implements Serializable {
    String s = "test"
}


сначала делаю сериализацию для объекта:

Foo foo = new Foo();
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
writeObject(foo);
flush();
close();


получаю бинарный файл с объектом, а как мне передать и загрузить классы, чтобы можно
было прочитать этот файл?
    


Ответы

Ответ 1



Как то так: import java.io.*; public class Foo implements Serializable { private Bar bar; private Foo() { bar = new Bar(); } public static void main(String[] args) { String filename = "foo.ser"; Foo foo = new Foo(); try (FileOutputStream fos = new FileOutputStream(filename); ObjectOutputStream out = new ObjectOutputStream(fos)) { out.writeObject(foo); } catch (Exception ex) { ex.printStackTrace(); } Bar bar = null; try (FileInputStream fis = new FileInputStream(filename); ObjectInputStream in = new ObjectInputStream(fis)) { bar = ((Foo) in.readObject()).getBar(); } catch (Exception ex) { ex.printStackTrace(); } System.out.println(bar.getText()); } private Bar getBar() { return bar; } } class Bar implements Serializable { private String text; Bar() { text = "test"; } public String getText() { return text; } }

Ответ 2



Сериализация и так всегда сохраняет тип объекта. Так что, если Foo и Bar доступны компилятору читающего кода, всё просто: Object o = oin.readObject(); Foo f = null; Bar b = null; if (o instanceof Foo) f=(Foo) o; if (o instanceof Bar) b=(Bar) o; или if (o.getClass()==Foo.class) f=(Foo) o; Если классы Foo/Bar недоступны читающему коду в принципе, то при чтении будет ClassNotFoundException . Теоретически, сами Foo.class и Bar.class сериализуются, но передать их потом в ObjectInputStream - отдельная история. Например, говорят, что можно переопределить метод ResolveClass: https://community.oracle.com/thread/1151865 , но это не готовое решение.

Ответ 3



Файл будет десереализован в объект типа вашего класса, потом можно с помощью .getClass() получить класс объекта, если он вам действительно нужен Если необходимо просто десереализовать объект то для этого нет необходимости предварительно получать класс будущего объекта если же нужно потом вызвать метод этого объекта, при чем у вас нет ни интерфейса ни класса объекта то стоит посмотреть в сторону Class c = obj.getClass(); Method m = c.getDeclaredMethod("methodName"); m.invoke(obj);

четверг, 26 декабря 2019 г.

Сериализация в Windows Phone 7.

#c_sharp #silverlight #windows_phone_7 #visual_studio #serializable


Доброго времени суток, Хэшкод.
Пытаюсь сделать Serializable class, по привычке пишу:
using System.Runtime.Serialization;

namespace someNamespace
{
    [Serializable()]
    public sealed class SomeClass: ISerializable
    {
        private readonly long someField;
        .
        .
        .
    }

Однако под WinPhone7 это не работает, VS радостно заявляет, что не знает, что такое
Serializable & ISerializable. Как это исправить? Приложение является портом с Java(Android),
насколько помню Javовское "implements Serializable" это как раз C#-ское ":ISerializable".
Не может такого быть, чтоб под winPhone не было такой возможности.    


Ответы

Ответ 1



Дело в том, что для Windows Phone нужно использовать вместо атрибута Serializable атрибут DataContract. Кое-какие подробности: DataContract DataContractSerializer

суббота, 16 марта 2019 г.

Deserialize вариационных (типизированных) XML

Раньше не сталкивался с сериализацией объектов, особенно с сериализацией в XML и обратно, но пришлось - да не знаю как быть с объектами в которых присутствует поле класса Object, в котором могут быть объекты нескольких типов. Пример XML 123 1001 232 1001 943 TheName Пример XML Error Message Предполагаю, что классы можно записать так (хотя в записи не уверен, ибо не работает): [XmlRootAttribute("Entities", Namespace = "http://site.org/", IsNullable = false)] public class BoxPackages { [XmlArray(IsNullable = true)] public BoxError Error; [XmlArray(IsNullable = true)] public object[] Package; }
public class BoxError { public String Message; }
[XmlRootAttribute("TypeA")] public class PackageTypeA { public Int32 ID; public Int64 Number; }
[XmlRootAttribute("TypeB")] public class PackageTypeB { public Int32 ID; public Byte Type; }
[XmlRootAttribute("TypeC")] public class PackageTypeC { public Int32 ID; public String Name; } Понятно, что классов не достаточно - нужна ещё какая-то настройка сериализатора. Кто знает, как настроить сериализатор (XmlAttributes из коробки) для десериализации XML в объект типа BoxPackages? Подскажите, пожалуйста?


Ответ

Класс XmlSerializer умеет сериализовать только известные типы. Т.к. в массве object[] может быть любой объект любого типа, в конструкторе этого класса надо перечислить все возможные типы объектов, которые предполагается использовать: Type [] extraTypes = new Type[3]; extraTypes[0] = typeof(PackageTypeA); extraTypes[1] = typeof(PackageTypeB); extraTypes[2] = typeof(PackageTypeC);
// Create the XmlSerializer instance. XmlSerializer mySerializer = new XmlSerializer(typeof(BoxPackages),extraTypes); Этот пример основан на XmlSerializer - конструктор

четверг, 10 января 2019 г.

Сериализация в С++

Прошу дать ссылки, или, если есть желание, рассказать вкратце о красивом, удобном способе сериализации полей класса в C++. Приведу пример (не уверен, что так можно, но хотелось бы) - использовать свойства, аналогичные свойствам в C#, перед полями, которые будут учавствовать в сериализации (но: рефлексия ?), все автоматически упаковывается в JSON/XML (если это важно, то JSON меня интересует в большей степени), аналогично читается из JSON/XML и инициализирует соостветствующие поля объекта.


Ответ

Универсального решения нет - и быть не может без рефлексии - которая будет - возможно - только в следующих версиях плюсов - да и с ней - если будут накладные расходы - универсального решения не будет. Вы можете выбирать из библиотек. По скорости или удобству использования.
"свойства, аналогичные свойствам в C#, перед полями" реализуются всеми этими либами через макросы (слегка приврал), многое из того, что раньше можно было достичь только макросами сейчас можно достижимо средствами шаблонов C++, но:
вот пример использования boost::serialization c макросами. Пример добавления рефлексии с шаблонами и макросами. RTTI с макросами
Сами по себе макросы - зло, но бывают и необходимым злом.
я для себя взял rapidjson (пушо очень быстрая) и сделал вокруг нее пару обвязок типа stringValue / intValue. В принципе, достаточно удобно пока.
По поводу бустов: попользуйтесь, наверняка будет полезно. Выпиливать куски не надо, на рантайм это не повлияет, может быть только на время компиляции. Если подойдет другая либа для json/xml (POCO) например, берите ту, что вам удобнее в использовании. Вам главное инкапсулировать как можно больше, чтобы вы могли сменить потом либу, а не ловить ее вызовы по всему коду

среда, 19 декабря 2018 г.

Как пометить класс как [Serializable] ,если он подгружается из dll

Я использую dll файлы в моем проекте. Как пометить класс как сериализуемый атрибутом [serializable]. Я не имею исходного кода, только dll файл, на который есть ссылка в моем классе. Я хочу сделать его сериализуемым, чтобы использовать состояние представления для моего объекта, который использует dll. Использую бинарную сериализацию. Как решить проблему?


Ответ

Если вы можете вручную, кодом, извлечь из такого объекта все нужные свойства, то можно использовать механизм Surrogate Selector. Код честно взят из MSDN. Employee - тот самый "внешний" класс, на который нельзя поставить [Serializable]
using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Serialization.Formatters.Binary;
// This class is not serializable. class Employee { public String name, address;
public Employee(String name, String address) { this.name = name; this.address = address; } }
// This class can manually serialize an Employee object. sealed class EmployeeSerializationSurrogate : ISerializationSurrogate {
// Serialize the Employee object to save the object's name and address fields. public void GetObjectData(Object obj, SerializationInfo info, StreamingContext context) {
Employee emp = (Employee) obj; info.AddValue("name", emp.name); info.AddValue("address", emp.address); }
// Deserialize the Employee object to set the object's name and address fields. public Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) {
Employee emp = (Employee) obj; emp.name = info.GetString("name"); emp.address = info.GetString("address"); return null; } }
public sealed class App { static void Main() { // This sample uses the BinaryFormatter. IFormatter formatter = new BinaryFormatter();
// Create a MemoryStream that the object will be serialized into and deserialized from. using (Stream stream = new MemoryStream()) { // Create a SurrogateSelector. SurrogateSelector ss = new SurrogateSelector();
// Tell the SurrogateSelector that Employee objects are serialized and deserialized // using the EmployeeSerializationSurrogate object. ss.AddSurrogate(typeof(Employee), new StreamingContext(StreamingContextStates.All), new EmployeeSerializationSurrogate());
// Associate the SurrogateSelector with the BinaryFormatter. formatter.SurrogateSelector = ss;
try { // Serialize an Employee object into the memory stream. formatter.Serialize(stream, new Employee("Jeff", "1 Microsoft Way")); } catch (SerializationException e) { Console.WriteLine("Serialization failed: {0}", e.Message); throw; }
// Rewind the MemoryStream. stream.Position = 0;
try { // Deserialize the Employee object from the memory stream. Employee emp = (Employee) formatter.Deserialize(stream);
// Verify that it all worked. Console.WriteLine("Name = {0}, Address = {1}", emp.name, emp.address); } catch (SerializationException e) { Console.WriteLine("Deserialization failed: {0}", e.Message); throw; } } } }
// This code produces the following output. // // Name = Jeff, Address = 1 Microsoft Way
т.е. сериализоваться будет класс без аттрибута [Serializable], но как именно его сериализовать - вам придется описать самому.

пятница, 30 ноября 2018 г.

Сериализация в Windows Phone 7.

Доброго времени суток, Хэшкод. Пытаюсь сделать Serializable class, по привычке пишу: using System.Runtime.Serialization;
namespace someNamespace { [Serializable()] public sealed class SomeClass: ISerializable { private readonly long someField; . . . } Однако под WinPhone7 это не работает, VS радостно заявляет, что не знает, что такое Serializable & ISerializable. Как это исправить? Приложение является портом с Java(Android), насколько помню Javовское "implements Serializable" это как раз C#-ское ":ISerializable". Не может такого быть, чтоб под winPhone не было такой возможности.


Ответ

Дело в том, что для Windows Phone нужно использовать вместо атрибута Serializable атрибут DataContract. Кое-какие подробности: DataContract DataContractSerializer