2014-07-14 9 views
6

Mam listę typów, które muszę zapisać do pliku i przeczytać go po. używam DataContractSerializer ale otrzymuję wyjątek podczas deserializacji:Serialize/deserialize System.RuntimeType

nie można odnaleźć konstruktora z argumentami (SerializationInfo, StreamingContext) w ISerializable "System.RuntimeType".

Dodałem System.RuntimeType jako znany typ do mojego serializera, ale to nie pomogło.

Oto kod z moich dwóch metod

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

serializacji wydaje się działać prawidłowo, a plik wyjściowy jest ok, ale problem zaczyna się na deserializacji:

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 
    } 

Czy istnieje jakiś sposób, aby przejść to? A może istnieje inny sposób przechowywania typów?

+3

Powinieneś serializować dane **, a nie implementację. "Typ" to 100% o implementacji. Szczerze mówiąc, jest to po prostu zła droga, a byłoby to nieużytek, aby pomóc ci pójść dalej tą mroczną ścieżką. IMO. –

+0

Dokonuję serializacji danych, ale zawiera typy zdefiniowane przez użytkownika, do których nie mogę uzyskać dostępu. Kiedy je deserializuję, muszę znać te typy. Myślałem, że jedynym sposobem uzyskania dostępu do nich jest przechowywanie ich w pliku. –

Odpowiedz

2

Marc Gravell ma rację, prawdopodobnie powinieneś serializować dane, a nie typy.

Ale z jakiegoś powodu, jeśli naprawdę chcesz serializować same typy, to nie powinieneś serializować obiektu Type (całkiem pewny, że nie jest on dostępny dla serailizable). W każdym razie zamiast tego serializuj Type.FullName. Podczas ładowania typów, należy 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)); 
    } 
} 

Uwaga: Podczas pracy z dowolnym Stream (lub tak naprawdę każde IDisposable) trzeba albo wywołać metodę Dispose lub użyć instrukcji using (jak ja powyżej). Zapewnia to poprawne czyszczenie IDisposable (tj. Zwalnia uchwyty systemu plików).

+0

Z jakiegoś powodu nie mogę znaleźć metody Type.Load. Jesteś pewien, że to istnieje? –

+1

Prawdopodobnie zamierzał serializować ['Type.AssemblyQualifiedName'] (https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname%28v=vs.110%29.aspx) zamiast' Type .FullName', aby załadować typ za pomocą ['Type.GetType'] (https://msdn.microsoft.com/en-us/library/w3f99sx1%28v=vs.110%29.aspx) zamiast nieistniejącego' Type.Load' i prawdopodobnie powinien zasugerować użycie ['IDataContractSurrogate'] (https://msdn.microsoft.com/en-us/library/system.runtime.serialization.idatacontractsurrogate%28v=vs.110%29. aspx) zamiast ręcznego podstawiania wartości przed/po serializacji. – binki