2014-09-12 73 views
2

我想序列化一个类作为属性。以下是用例:我需要将大量工程参数存储在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> 

我的问题是非常相似的一问here。与他不同,我很好地实现了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); 
    } 
    } 
+0

看看内部异常:““无法序列成员‘ConsoleApplication2.MyObject.A’类型‘ConsoleApplication2.MyParam’,请参阅内部异常的更多细节。”',然后去看看那个内部异常: '“ConsoleApplication2.MyParam不能被序列化,因为它没有无参数的构造函数。” – 2014-09-12 17:11:50

回答

0

为了得到你想要的东西,你需要控制包含属性的容器的序列化,而不是属性本身。您仍然可以将序列化代码封装在属性中,如下所示。

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); 
    } 
} 
0

后,我已经添加了参数的构造函数,我得到了以下异常: 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.并发现this answer

this后。

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

相关问题