2014-07-14 1 views
6

Ich habe eine Liste von Typen, die ich brauche zu speichern, nachdem die Datei und zu lesen. Ich benutze DataContractSerializer aber ich erhalte eine Ausnahme während der Deserialisierung:Serialize/deserialisieren System.RuntimeType

nicht gefunden Konstruktor mit Argumenten (SerializationInfo, Streaming) in ISerializable "System.RuntimeType".

Ich habe System.RuntimeType als einen bekannten Typ zu meinem Serializer hinzugefügt, aber es hat nicht geholfen.

Hier Code meiner beiden Methoden

public static void SaveTypes(List<Type> types, string fileName) 
{ 
    Type rt = types[0].GetType(); 

    List<Type> knownTypes = new List<Type>() { rt }; //I get a List with System.RuntimeType item here 
    DataContractSerializer serializer = new DataContractSerializer(typeof(List<Type>), knownTypes); 
    XmlWriterSettings settings = new XmlWriterSettings(); 
    settings.Indent = true; 
    Stream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write); 
    using (XmlWriter xw = XmlWriter.Create(fs, settings)) 
     serializer.WriteObject(xw, types); 
} 

Serialisierung scheint gut zu funktionieren, und die Ausgabedatei ist in Ordnung, aber Problem beginnt am Deserialisieren:

public static object LoadTypes(string fileName) 
    { 
     Stream file = new FileStream(fileName, FileMode.Open, FileAccess.Read); 
     byte[] data = new byte[file.Length]; 
     file.Read(data, 0, (int)file.Length); 

     Type rt = file.GetType(); 
     List<Type> knownTypes = new List<Type>() { rt.GetType() }; 
     DataContractSerializer deserializer = new DataContractSerializer(typeof(List<Type>), knownTypes); 

     Stream stream = new MemoryStream(); 
     stream.Write(data, 0, data.Length); 
     stream.Position = 0; 
     return deserializer.ReadObject(stream); //exception here 
    } 

Gibt es einen Weg zu durchlaufen Dies? Oder gibt es eine andere Möglichkeit, Typen zu speichern?

+3

Sie sollten die ** Daten ** serialisieren, nicht die Implementierung. Ein 'Type' steht zu 100% für die Implementierung. Ehrlich gesagt, ist es einfach der falsche Weg, und es wäre ein schlechter Dienst, Ihnen zu helfen, diesen dunklen Weg weiter zu gehen. IMO. –

+0

Ich serialisiert die Daten, aber es enthält benutzerdefinierte Typen, auf die ich keinen Zugriff habe. Also, wenn ich sie deserialize, muss ich diese Typen kennen. Ich dachte, der einzige Weg, um Zugang zu ihnen zu bekommen, ist sie in einer Datei zu speichern. –

Antwort

2

Marc GRA ist richtig, Sie sollten wahrscheinlich die Daten werden serialisiert und nicht die Typen.

Aber aus irgendeinem Grund, wenn Sie wirklich die Typen selbst serialisiert werden wollen, dann sollten Sie das Type-Objekt nicht serialisiert werden (ziemlich sicher, es ist nicht serailizable). Wie auch immer, serialisieren Sie stattdessen Type.FullName. Wenn Sie die Typen laden, verwenden Type.Load

public static void SaveTypes(IEnumerable<Type> types, string filename) 
{ 
    using (var fs = File.Open(filename, FileMode.OpenOrCreate) 
     new XmlSerializer(typeof(string[])) 
      .Serialize(fs, types.Select(t => t.FullName).ToArray()) 
} 

pubic static IEnumerable<Type> LoadTypes(string filename) 
{ 
    using (var fs = File.Open(filename, FileMode.Open) 
    { 
     var typeNames = (string[]) 
      new XmlSerializer(typeof(string[])) 
      .Deserialize(fs); 

      return typeNames.Select(t => Type.Load(t)); 
    } 
} 

Hinweis: Wenn mit jedem Stream (oder wirklich jede IDisposable) arbeiten, haben Sie entweder die Dispose Methode aufrufen oder die using Anweisung verwenden (wie ich oben tat). Dies stellt sicher, dass die IDisposable ordnungsgemäß bereinigt wird (dh die Dateisystemhandles freigibt).

+0

Aus irgendeinem Grund kann ich die Type.Load-Methode nicht finden. Bist du sicher, dass es existiert? –

+1

Er wahrscheinlich serialisiert gemeint [ 'Type.AssemblyQualifiedName'] (https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname%28v=vs.110%29.aspx) anstelle von' Type .FullName', um den Typ mit ['Type.GetType'] (https://msdn.microsoft.com/en-us/library/w3f99sx1%28v=vs.110%29.aspx) statt mit dem nicht vorhandenen' 'zu laden Type.Load', und sollte wahrscheinlich vorgeschlagen haben, ['IDataContractSurrogate'' zu verwenden (https://msdn.microsoft.com/en-us/library/system.runtime.serialization.idataccontractsurrogate%28v=vs.110%29. aspx) anstatt die Werte vor/nach der Serialisierung manuell zu ersetzen. – binki