如何将类序列化为属性

本文关键字:属性 序列化 | 更新日期: 2023-09-27 18:21:44

我正在尝试将类序列化为属性。用例如下:我需要在xml配置文件中存储大量的工程参数。这涉及到科学记数法,客户要求输入的值保持与用户输入的值完全相同的形式。例如,如果有人输入"5.3e-1",那么它必须保持原样,并且不能转换为"0.53"。为此,我创建了一个Params类,它存储输入的字符串和双值(实际上存储双值只是为了以后的处理效率)。现在的诀窍是:我只希望字符串值被序列化,并且我希望它被序列化为一个属性。

例如,如果一个对象包含两个参数A和B,其中字符串值为A.stringVal="1.2e5"和B.stringVal="2.0",那么我希望:

public class MyObject
{
    [XmlAttribute]
    public MyParam A { get; set; }
    [XmlAttribute]
    public MyParam B { get; set; }
    ...more stuff...
}

要序列化为:

<myObject A="1.2e5" B="2.0">
    more stuff...
</myObject>

我的问题与这里提出的问题非常相似。与他不同的是,我可以很好地实现IXmlSerializable(并且更愿意),但我就是无法实现它。当我试图序列化它时,我会得到一个神秘的异常,说:"有错误反射类型。"我做错了什么?

  public class MyParam : IXmlSerializable
  {
     string name;
     string stringVal;
     double doubleVal;
     public string Val
     {
        get
        {
           return stringVal;
        }
        set
        {
           stringVal = value;
           doubleVal = double.Parse(value);
        }
     }
     public double DoubleVal
     {
        get
        {
           return doubleVal;
        }
        set
        {
           doubleVal = value;
           stringVal = value.ToString();
        }
     }
     public MyParam(string name)
     {
        this.name = name;
        this.stringVal = string.Empty;
        this.doubleVal = double.NaN;
     }
     public System.Xml.Schema.XmlSchema GetSchema()
     {
        return null;
     }
     public void ReadXml(System.Xml.XmlReader reader)
     {
        throw new NotImplementedException();
     }
     public void WriteXml(System.Xml.XmlWriter writer)
     {
        writer.WriteAttributeString(name, stringVal);
     }
  }

如何将类序列化为属性

要获得所需内容,需要控制包含属性的容器上的序列化,而不是属性本身。但是,您仍然可以将序列化代码封装在属性中,请参阅下文。

public class MyObject : IXmlSerializable
{
    public MyParam A { get; set; }
    public MyParam B { get; set; }
    public XmlSchema GetSchema()
    {
        return null;
    }
    public void ReadXml(XmlReader reader)
    {
        throw new NotImplementedException();
    }
    public void WriteXml(XmlWriter writer)
    {
        //Call each properties "WriteAttribute" call.
        A.WriteAttribute(writer);
        B.WriteAttribute(writer);
    }
}
public class MyParam
{
    string name;
    string stringVal;
    double doubleVal;
    public string Val
    {
        get
        {
            return stringVal;
        }
        set
        {
            stringVal = value;
            doubleVal = double.Parse(value);
        }
    }
    public double DoubleVal
    {
        get
        {
            return doubleVal;
        }
        set
        {
            doubleVal = value;
            stringVal = value.ToString();
        }
    }
    public MyParam(string name)
    {
        this.name = name;
        this.stringVal = string.Empty;
        this.doubleVal = double.NaN;
    }
    internal void WriteAttribute(XmlWriter writer)
    {
        writer.WriteAttributeString(name, stringVal);
    }
}
class Program
{
    static void Main(string[] args)
    {
        var test = new MyObject()
        {
            A = new MyParam("A"),
            B = new MyParam("B"),
        };
        test.A.Val = "1.2e5";
        test.B.Val = "2.0";
        var ser = new XmlSerializer(typeof(MyObject));
        var sb = new StringBuilder();
        using (var stream = new StringWriter(sb))
        {
            ser.Serialize(stream, test);
        }
        Console.WriteLine(sb);
        Console.ReadLine();
    }
}

输出

<?xml version="1.0" encoding="utf-16"?>
<MyObject A="1.2e5" B="2.0" />

如果您不需要属性本身中的属性名称,则可以将代码修改为以下内容。

public class MyObject : IXmlSerializable
{
    //....
    public void WriteXml(XmlWriter writer)
    {
        //Call each properties "WriteAttribute" call.
        A.WriteAttribute(writer, "A");
        B.WriteAttribute(writer, "B");
    }
}
public class MyParam
{
    //...
    public MyParam()
    {
        this.stringVal = string.Empty;
        this.doubleVal = double.NaN;
    }
    internal void WriteAttribute(XmlWriter writer, string name)
    {
        writer.WriteAttributeString(name, stringVal);
    }
}

添加无参数构造函数后,出现以下异常:The element 'A' type ConsoleApplication1.MyParam can not be serialized. XmlAttribute / XmlText can not be used to encode types that implement IXmlSerializable.

删除IXmlSerializable后,我得到了一个异常XmlAttribute/XmlText cannot be used to encode complex types.,并找到了这个答案

还有这个。

因此,我认为,最好找到另一种序列化属性的方法。