2016-04-26 63 views
0

我試圖設置一個可靠的方法來更新我的軟件,以確保我可以平穩地更新我的用戶文件,每當我發佈程序更新。該軟件是用C#編寫的。如何有效地將舊的XML對象轉換爲新更新的XML對象?

說我有一個Person對象:

- Name 
- DoB 
- Nationality 

所以這是我的個人類的0.1版本。在未來,爲了舉例,我向人物對象(v0.2)介紹了一些新的領域。

- Name 
- DoB 
- Nationality 
- Temperament <- NEW 
- Job <- NEW 

顯然我需要將舊對象更新爲新對象。我正在做的是以下幾點:

  1. 將0.1對象讀入版本化類(如Person01.cs)。
  2. 用舊對象具有的字段填充新對象。
  3. 用默認值填充新對象的新字段。
  4. 寫出文件。

這看起來效率非常低。每次我做任何改變都需要大量的自定義編碼。必須有更好的方法來做到這一點,但因爲這是我第一次真正使用XML,所以我不確定如何去做。任何幫助,你可以提供將不勝感激。我已經尋找解決這個問題的辦法,但我只找到無關的結果。

+0

感謝位,良好的通話。這有助於可讀性。我很久沒有在這裏發佈了。 –

+0

如果您手動創建xml,這將是不夠的。您是否使用XmlSerializer:https://msdn.microsoft.com/en-us/library/bb675182.aspx? – bit

+0

是啊System.Xml.Serialization –

回答

1

我們有一個Person對象:

public class Person 
{ 
    public string Name { get; set; } 
    public DateTime DoB { get; set; } 
    public string Nationality { get; set; } 
} 

然後我們添加新的屬性。不需要有不同版本的課程!只需添加屬性和默認構造函數,在其中設置新的屬性值。反序列化將設置這些值,而不是丟失。

public class Person 
{ 
    public Person() 
    { 
     // set default value 
     Temperament = "hot"; 
     Job = "office slave"; 
    } 

    public string Name { get; set; } 
    public DateTime DoB { get; set; } 
    public string Nationality { get; set; } 

    public string Temperament { get; set; } 
    public string Job { get; set; } 
} 
+0

非常感謝你!這很簡單。正是我希望找到的。現在,當我更新時,我需要做的是爲每個新變量添加默認值。 –

1

您可以通過將舊的xml反序列化爲新的對象來縮短步驟1 & 2,例如假如你想知道一個人V1,如:

[XmlRoot("Person")] 
public class PersonV1 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

然後你把它升級到人V2,如:

[XmlRoot("Person")] 
public class PersonV2 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string MiddleName { get; set; } 
    public DateTime BirthDate { get; set; } 
} 

現在你可以填充數據的人V2你的人V1像閱讀:

// read from person v1 
var p1 = new PersonV1(); 
p1.FirstName = "Jeff"; 
p1.LastName = "Price"; 
var xmlSerializer = new XmlSerializer(typeof(PersonV1)); 
var stream = new MemoryStream(); 
xmlSerializer.Serialize(stream, p1); 
var xmlStringP1 = Encoding.ASCII.GetString(stream.ToArray()); 

// populate to person v2 
var deserializer = new XmlSerializer(typeof(PersonV2)); 
TextReader reader = new StringReader(xmlStringP1); 
var p2 = (PersonV2)deserializer.Deserialize(reader); 

// further, set defaults for person v2 

您可以在這裏探索更多用於xml序列化的定製:http://www.codeproject.com/Articles/483055/XML-Serialization-and-Deserialization-Part-1

+0

我正在嘗試這個想法,但它似乎並沒有爲我工作。我得到一個錯誤,反序列化器似乎不喜歡類別具有不同名稱的事實「InvalidOperationException:不是預期的」 –

+0

是的,這就是爲什麼有* XmlRoot *屬性在那個地方。你是否用它來取消不同類名的影響?還請查看底部鏈接中的其他選項 – bit

+0

您是對的,那是我的錯誤。我跟着Alex說了什麼,但你的回答很好,謝謝。 –

1

一個很好的簡單解決方案是使用XSL轉換。您可以簡單地將轉換應用於XML文件或字符串與XML數據,並添加新的屬性。如何在C#中執行此操作的示例可以找到here

一個例子XML文件:

<?xml version="1.0" encoding="utf-8"?> 
<person> 
    <name>John</name> 
    <DoB>2016-01-01</DoB> 
</person> 

一個例子XSL文件:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> 
    <xsl:output method="xml" encoding="UTF-8" indent="no"/> 
    <xsl:template match="/"> 
     <person> 
      <xsl:element name="name"> 
       <xsl:value-of select="/person/name"/> 
      </xsl:element> 
      <xsl:element name="DoB"> 
       <xsl:value-of select="/person/DoB"/> 
      </xsl:element> 
      <Temperament>Quick to anger</Temperament> 
      <Job>Unemployed</Job> 
     </person> 
    </xsl:template> 
</xsl:stylesheet> 

其結果將是:

<?xml version="1.0" encoding="UTF-8"?> 
<person> 
    <name>John</name> 
    <DoB>2016-01-01</DoB> 
    <Temperament>Quick to anger</Temperament> 
    <Job>Unemployed</Job> 
</person>