2014-09-12 55 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後。

所以,我認爲,最好是找到另一種序列化屬性的方法。