2014-04-08 3 views
6

Ich versuche, eine Speicherroutine für meine Anwendung zu schreiben, wo mehrere Teile der Anwendung Elemente zu einem Dictionary hinzufügen und dann die Speicherfunktion in a schreibt XML-Datei. Die offene Routine muss diese Dateien lesen und das Dictionary neu füllen und diese Objekte dann wieder in meine Anwendung einfügen. Ich kämpfe mit der Deserialisierung der Routine, die ich jetzt habe. Mein speichern Routine alsWie man ein Dictionary <string, object> in XML serialisiert/deinserialisiert

XmlDocument xmlDoc = new XmlDocument(); 

// Write down the XML declaration 
XmlDeclaration xmlDeclaration = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null); 

// Create the root element 
XmlElement rootNode = xmlDoc.CreateElement("TireStudy"); 
xmlDoc.InsertBefore(xmlDeclaration, xmlDoc.DocumentElement); 
xmlDoc.AppendChild(rootNode); 

foreach (var saveItem in _SaveItems) 
{ 
    XPathNavigator nav = rootNode.CreateNavigator(); 
    using (var writer = nav.AppendChild()) 
    { 
     var serializer = new XmlSerializer(saveItem.Value.GetType()); 
     writer.WriteWhitespace(""); 
     serializer.Serialize(writer, saveItem.Value); 
     writer.Close(); 
    } 
} 

xmlDoc.Save(fileName); 

Diese Routine funktioniert folgt, ist eine Datei zu erstellen, aber ich würde der Schlüsselwert des Wörterbuchs wie auch in der Datei gespeichert werden, und ich bin nicht sicher, wie das deserialisieren Datei erstellt, weil ich die Arten der Objekte nicht kenne, bevor ich sie lese.

Teil 2 (ich hasse das Hinzufügen neuer Teile auf eine Frage, aber ich weiß nicht, einen besseren Weg sehen, die Probleme für die Zukunft zu adressieren)

ich jetzt den folgenden Code haben,

var knownTypes = new List<Type> 
{ 
    typeof(ObservableCollection<string>), 
    typeof(ObservableCollection<Segments>), 
    typeof(Segments), 
    typeof(List<string>) 
}; 
var serialized = _SaveItems.Serialize(knownTypes); 

aber ich erhalte die folgende Ausnahme

Type 'System.Collections.Generic.List`1[System.String]' cannot be added to list of known types since another type 'System.Collections.ObjectModel.ObservableCollection`1[System.String]' with the same data contract name 'http://schemas.microsoft.com/2003/10/Serialization/Arrays:ArrayOfstring' is already present. If there are different collections of a particular type - for example, List<Test> and Test[], they cannot both be added as known types. Consider specifying only one of these types for addition to the known types list. 

Wenn ich entweder die typeof (ObservableCollection) oder die typeof (List) es Ausnahmen löschen beschweren sie die man braucht, ich gelöscht.

+0

In Bezug auf Teil 2, bin ich nicht sicher Wenn dies ein Framework [Einschränkung] (http://msdn.microsoft.com/en-us/library/aa347850.aspx) oder [Bug] (http://support.microsoft.com/kb/967339). – xmamat

+0

So oder so, ich habe gerade meine Liste losgeworden und ObservableCollection in meiner Klasse verwendet und das Leben wurde einfacher. Danke für Ihre Hilfe. – PlTaylor

Antwort

3

Sie DataContractSerializer nutzen könnten, wie in diesem post erklärt Sie können jedoch die bekannten Typen als Parameter an den Serializer passieren müssen verschachtelte object getippt Klassen zu unterstützen:

using System; 
using System.Collections.Generic; 
using System.Runtime.Serialization; 
using System.IO; 
using System.Xml; 

public static class SerializationExtensions 
{ 
    public static string Serialize<T>(this T obj, IEnumerable<Type> knownTypes) 
    { 
     var serializer = new DataContractSerializer(obj.GetType(), knownTypes); 
     using (var writer = new StringWriter()) 
     using (var stm = new XmlTextWriter(writer)) 
     { 
      serializer.WriteObject(stm, obj); 
      return writer.ToString(); 
     } 
    } 
    public static T Deserialize<T>(this string serialized, IEnumerable<Type> knownTypes) 
    { 
     var serializer = new DataContractSerializer(typeof(T), knownTypes); 
     using (var reader = new StringReader(serialized)) 
     using (var stm = new XmlTextReader(reader)) 
     { 
      return (T)serializer.ReadObject(stm); 
     } 
    } 
} 

public class Address 
{ 
    public string Country { get; set; } 
    public string City { get; set; } 
} 
public class CodedAddress 
{ 
    public int CountryCode { get; set; } 
    public int CityCode { get; set; } 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     var persons1 = new Dictionary<string, Address>(); 
     persons1.Add("John Smith", new Address { Country = "US", City = "New York" }); 
     persons1.Add("Jean Martin", new Address { Country = "France", City = "Paris" }); 

     // no need to provide known types to the serializer 
     var serializedPersons1 = persons1.Serialize(null); 
     var deserializedPersons1 = serializedPersons1.Deserialize<Dictionary<string, Address>>(null); 


     var persons2 = new Dictionary<string, object>(); 
     persons2.Add("John Smith", new Address { Country = "US", City = "New York" }); 
     persons2.Add("Jean Martin", new CodedAddress { CountryCode = 33, CityCode = 75 }); 

     // must provide known types to the serializer 
     var knownTypes = new List<Type> { typeof(Address), typeof(CodedAddress) }; 
     var serializedPersons2 = persons2.Serialize(knownTypes); 
     var deserializedPersons2 = serializedPersons2.Deserialize<Dictionary<string, object>>(knownTypes); 
    } 
} 
+0

Meine Google-Fu kommt hier ernsthaft kurz. Ich habe den besseren Teil von gestern damit verbracht, das zu untersuchen und bin nicht darauf gekommen, oder die Bedeutung war für mich verloren. Lass mich das ausprobieren und komme zu dir zurück. – PlTaylor

+0

Ich erhalte die folgende Ausnahme bei der Serialisierung: Geben Sie 'MyProgram.InformationTabs.NavigationTrees.SitesViewModel' mit dem Datenvertragsnamen 'SitesViewModel: http: //schemas.datacontract.org/2004/07/MyProgram.InformationTabs.NavigationTrees' ein. ' wird nicht erwartet. Ziehen Sie die Verwendung eines DataContractResolvers in Betracht oder fügen Sie statisch unbekannte Typen zur Liste bekannter Typen hinzu, z. B. indem Sie das KnownTypeAttribute-Attribut verwenden oder diese zur Liste bekannter Typen hinzufügen, die an DataContractSerializer übergeben werden. Irgendwelche Ideen, wie man das richtig dekorieren kann? – PlTaylor

+0

Sie haben recht: Man muss die bekannten Typen bereitstellen, damit der Serializer mit 'Dictionary ' arbeiten kann. Ich habe meine Antwort aktualisiert, um Ihre Anforderung zu erfüllen. Wahrscheinlich nicht der eleganteste Weg, um es zu tun, aber ich fand es zu arbeiten. – xmamat

Verwandte Themen