2016-04-26 4 views
0

Ich versuche, in Zukunft eine zuverlässige Methode zur Aktualisierung meiner Software einzurichten, indem ich sicherstelle, dass ich die Dateien meines Benutzers problemlos aktualisieren kann, wenn ich ein Programmupdate herausgebe. Die Software ist in C# geschrieben.Wie könnte ich ein altes XML-Objekt effizient in ein neu aktuelles XML-Objekt konvertieren?

sagen, dass ich eine Person zum Gegenstand haben:

- Name 
- DoB 
- Nationality 

das ist die Version 0.1 von meiner Person Klasse also. In Zukunft werde ich zum Beispiel einige neue Felder in das Personenobjekt einführen (v0.2).

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

Offensichtlich muss ich das alte Objekt auf das neue aktualisieren. Was ich gerade mache, ist folgendes:

  1. Lies das 0.1-Objekt in eine versionierte Klasse (wie Person01.cs).
  2. Füllen Sie das neue Objekt mit den Feldern, die das alte Objekt hatte.
  3. Füllen Sie die neuen Felder des neuen Objekts mit Standardwerten auf.
  4. Schreiben Sie die Datei aus.

Dies scheint enorm ineffizient. Es erfordert jedes Mal, wenn ich etwas ändere, eine große Menge an benutzerdefiniertem Code. Es muss einen besseren Weg geben, dies zu tun, aber da ich zum ersten Mal wirklich mit XML arbeite, bin ich mir nicht sicher, wie ich das anstellen soll. Jede Hilfe, die Sie zur Verfügung stellen können, wäre sehr willkommen. Ich habe nach einer Lösung für dieses Problem gesucht, aber ich finde nur unabhängige Ergebnisse.

+0

Dank Bit, guter Ruf. Das hilft bei der Lesbarkeit. Ich habe hier lange nicht mehr gepostet. –

+0

Falls Sie das XML manuell erstellen, wird es sehr vorsichtig sein. Verwenden Sie XmlSerializer: https://msdn.microsoft.com/en-us/library/bb675182.aspx? – bit

+0

Ja System.Xml.Serialization –

Antwort

1

Wir hatten eine Person Objekt:

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

Dann fügen wir neue Eigenschaften. Keine Notwendigkeit, verschiedene Versionen der Klasse zu haben! Fügen Sie einfach Eigenschaften und Standardkonstruktoren hinzu, in denen neue Eigenschaftenwerte festgelegt werden. Bei der Deserialisierung werden diese Werte festgelegt, anstatt zu fehlen.

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

Fantastisches Danke! Das ist so einfach. Genau das, was ich zu finden hoffte. Jetzt muss ich beim Aktualisieren nur Standardwerte für jede neue Variable hinzufügen. –

1

Sie könnten die Schritte 1 & 2 durch das Deserialisieren des alten XML in das neue Objekt z. Angenommen, Sie hatten eine Person v1 wie:

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

Dann Sie es zu Person v2 aufgerüstet wie:

[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; } 
} 

Jetzt können Sie die Person v2 mit Daten könnten Sie für Person v1 lesen wie:

// 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 

Sie könnten mehr Anpassungen für xml Serialisierungen erforschen hier: http://www.codeproject.com/Articles/483055/XML-Serialization-and-Deserialization-Part-1

+0

Ich versuche diese Idee, aber es scheint nicht zu funktionieren für mich. Ich bekomme einen Fehler, dass der Deserializer die Tatsache nicht mag, dass die Klassen einen anderen Namen haben "InvalidOperationException: wurde nicht erwartet" –

+0

Ja, deshalb gibt es ein * XmlRoot * -Attribut an dem Ort. Haben Sie damit die Wirkung verschiedener Klassennamen aufgehoben? Überprüfen Sie auch die anderen Optionen in der Verbindung unten – bit

+0

Sie haben Recht, das war mein Fehler. Ich ging mit dem, was Alex sagte, aber Ihre Antwort war eine gute Info, danke. –

1

Eine gute einfache Lösung ist XSL-Transformation zu verwenden. Sie können eine Transformation einfach auf eine XML-Datei oder eine Zeichenfolge mit XML-Daten anwenden und die neuen Eigenschaften hinzufügen. Ein Beispiel, wie dies in C# zu tun ist, finden Sie here.

Ein Beispiel XML-Datei:

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

Ein Beispiel XSL-Datei:

<?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> 

Und das Ergebnis wäre:

<?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> 
Verwandte Themen