How to serialize 'System.Numerics.Complex' using an XmlSerializer?

时间:2021-07-20 16:51:07

This is the XML output I get when a Complex[] object is serialized:

这是我在序列化Complex []对象时得到的XML输出:

<MyClass>               
    <Complex />
    <Complex />
    <Complex />
    <Complex />
</MyClass>

The Complex struct is marked as serializable, and being a struct, it has an implicit parameterless constructor. So why isn't each Complex object serializing its real and imaginary parts ? Does it have to do with the fact that the 'Real' and 'Imaginary' properties of the struct have getters but not setters ?

Complex结构被标记为可序列化,并且作为结构,它具有隐式无参数构造函数。那么为什么每个Complex对象都不能序列化它的实部和虚部呢?是否与结构的“真实”和“虚构”属性具有吸气剂而非设定者这一事实有关?

Thanks.

2 个解决方案

#1


2  

The XmlSerializer doesn't serialize properties which don't have a setter (IIRC it only serializers public properties with both public getter and setters). You have a few options:

XmlSerializer不会序列化没有setter的属性(IIRC它只使用公共getter和setter序列化公共属性)。你有几个选择:

  • Replace the System.Numerics.Complex type with a type which you create (and has a "full" property)
  • 用您创建的类型替换System.Numerics.Complex类型(并具有“完整”属性)

  • Change the MyClass class to handle the serialization (and deserialization) of the complex numbers, via the IXmlSerializable interface.
  • 更改MyClass类以通过IXmlSerializable接口处理复数的序列化(和反序列化)。

The second option is shown below.

第二个选项如下所示。

public class *_10523009
{
    public class MyClass : IXmlSerializable
    {
        public Complex[] ComplexNumbers;

        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            reader.ReadStartElement("MyClass");
            List<Complex> numbers = new List<Complex>();
            while (reader.IsStartElement("Complex"))
            {
                Complex c = new Complex(
                    double.Parse(reader.GetAttribute("Real")),
                    double.Parse(reader.GetAttribute("Imaginary")));
                numbers.Add(c);
                reader.Skip();
            }

            reader.ReadEndElement();
            this.ComplexNumbers = numbers.ToArray();
        }

        public void WriteXml(XmlWriter writer)
        {
            foreach (var complex in ComplexNumbers)
            {
                writer.WriteStartElement("Complex");
                writer.WriteStartAttribute("Real"); writer.WriteValue(complex.Real); writer.WriteEndAttribute();
                writer.WriteStartAttribute("Imaginary"); writer.WriteValue(complex.Imaginary); writer.WriteEndAttribute();
                writer.WriteEndElement();
            }
        }

        public override string ToString()
        {
            return "MyClass[" + string.Join(",", ComplexNumbers) + "]";
        }
    }
    public static void Test()
    {
        MyClass mc = new MyClass { ComplexNumbers = new Complex[] { new Complex(3, 4), new Complex(0, 1), new Complex(1, 0) } };
        XmlSerializer xs = new XmlSerializer(typeof(MyClass));
        MemoryStream ms = new MemoryStream();
        xs.Serialize(ms, mc);
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
        ms.Position = 0;
        MyClass mc2 = (MyClass)xs.Deserialize(ms);
        Console.WriteLine(mc2);
    }
}

#2


3  

It depends on the implementation of the serializer you are using to serialize the object.
If you try this, you will get what you are expecting:

它取决于您用于序列化对象的序列化程序的实现。如果你试试这个,你会得到你所期望的:

using System.IO;
using System.Numerics;
using System.Runtime.Serialization.Formatters.Soap;

public class Test {
    public static void Main() {
        var c = new Complex(1, 2);
        Stream stream = File.Open("data.xml", FileMode.Create);
        SoapFormatter formatter = new SoapFormatter();
        formatter.Serialize(stream, c);
        stream.Close();
    }
}

Instead, if you use classes in the System.Xml.Serialization namespace, you will get something similar to what you posted:

相反,如果您在System.Xml.Serialization命名空间中使用类,您将获得类似于您发布的内容:

using System;
using System.IO;
using System.Numerics;
using System.Xml.Serialization;

public class Test {
    public static void Main() {
        var c = new Complex(1, 2);
        XmlSerializer s = new XmlSerializer(typeof(Complex));
        StringWriter sw = new StringWriter();
        s.Serialize(sw, c);
        Console.WriteLine(sw.ToString());
    }
}

I think that this is due to the fact that the XmlSerializer will not serialize private members (as are m_real and m_imaginary in the Complex struct).

我认为这是因为XmlSerializer不会序列化私有成员(如复杂结构中的m_real和m_imaginary)。

#1


2  

The XmlSerializer doesn't serialize properties which don't have a setter (IIRC it only serializers public properties with both public getter and setters). You have a few options:

XmlSerializer不会序列化没有setter的属性(IIRC它只使用公共getter和setter序列化公共属性)。你有几个选择:

  • Replace the System.Numerics.Complex type with a type which you create (and has a "full" property)
  • 用您创建的类型替换System.Numerics.Complex类型(并具有“完整”属性)

  • Change the MyClass class to handle the serialization (and deserialization) of the complex numbers, via the IXmlSerializable interface.
  • 更改MyClass类以通过IXmlSerializable接口处理复数的序列化(和反序列化)。

The second option is shown below.

第二个选项如下所示。

public class *_10523009
{
    public class MyClass : IXmlSerializable
    {
        public Complex[] ComplexNumbers;

        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            reader.ReadStartElement("MyClass");
            List<Complex> numbers = new List<Complex>();
            while (reader.IsStartElement("Complex"))
            {
                Complex c = new Complex(
                    double.Parse(reader.GetAttribute("Real")),
                    double.Parse(reader.GetAttribute("Imaginary")));
                numbers.Add(c);
                reader.Skip();
            }

            reader.ReadEndElement();
            this.ComplexNumbers = numbers.ToArray();
        }

        public void WriteXml(XmlWriter writer)
        {
            foreach (var complex in ComplexNumbers)
            {
                writer.WriteStartElement("Complex");
                writer.WriteStartAttribute("Real"); writer.WriteValue(complex.Real); writer.WriteEndAttribute();
                writer.WriteStartAttribute("Imaginary"); writer.WriteValue(complex.Imaginary); writer.WriteEndAttribute();
                writer.WriteEndElement();
            }
        }

        public override string ToString()
        {
            return "MyClass[" + string.Join(",", ComplexNumbers) + "]";
        }
    }
    public static void Test()
    {
        MyClass mc = new MyClass { ComplexNumbers = new Complex[] { new Complex(3, 4), new Complex(0, 1), new Complex(1, 0) } };
        XmlSerializer xs = new XmlSerializer(typeof(MyClass));
        MemoryStream ms = new MemoryStream();
        xs.Serialize(ms, mc);
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
        ms.Position = 0;
        MyClass mc2 = (MyClass)xs.Deserialize(ms);
        Console.WriteLine(mc2);
    }
}

#2


3  

It depends on the implementation of the serializer you are using to serialize the object.
If you try this, you will get what you are expecting:

它取决于您用于序列化对象的序列化程序的实现。如果你试试这个,你会得到你所期望的:

using System.IO;
using System.Numerics;
using System.Runtime.Serialization.Formatters.Soap;

public class Test {
    public static void Main() {
        var c = new Complex(1, 2);
        Stream stream = File.Open("data.xml", FileMode.Create);
        SoapFormatter formatter = new SoapFormatter();
        formatter.Serialize(stream, c);
        stream.Close();
    }
}

Instead, if you use classes in the System.Xml.Serialization namespace, you will get something similar to what you posted:

相反,如果您在System.Xml.Serialization命名空间中使用类,您将获得类似于您发布的内容:

using System;
using System.IO;
using System.Numerics;
using System.Xml.Serialization;

public class Test {
    public static void Main() {
        var c = new Complex(1, 2);
        XmlSerializer s = new XmlSerializer(typeof(Complex));
        StringWriter sw = new StringWriter();
        s.Serialize(sw, c);
        Console.WriteLine(sw.ToString());
    }
}

I think that this is due to the fact that the XmlSerializer will not serialize private members (as are m_real and m_imaginary in the Complex struct).

我认为这是因为XmlSerializer不会序列化私有成员(如复杂结构中的m_real和m_imaginary)。