2014-07-14 15 views
6

Tôi có một Danh sách các loại mà tôi cần lưu vào tệp và đọc sau. tôi sử dụng DataContractSerializer nhưng tôi nhận được một ngoại lệ trong deserialization:Serialize/deserialize System.RuntimeType

Không thể tìm thấy nhà xây dựng với các đối số (SerializationInfo, StreamingContext) trong ISerializable "System.RuntimeType".

Tôi đã thêm System.RuntimeType như một loại biết đến serializer của tôi, nhưng nó đã không giúp đỡ.

Đây là mã của hai phương pháp của tôi

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

serialization dường như làm việc tốt, và các tập tin đầu ra là ok, nhưng vấn đề bắt đầu từ ngày deserializing:

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 
    } 

Có cách nào để đi qua điều này? Hoặc có thể có một số cách khác để lưu trữ các loại?

+3

Bạn nên tuần tự hóa ** dữ liệu **, chứ không phải triển khai. 'Loại' là 100% về việc triển khai. Thành thật mà nói, nó chỉ đơn giản là sai đường để đi, và nó sẽ là một sự bất hòa để giúp bạn đi xa hơn con đường tối đó. IMO. –

+0

Tôi làm tuần tự hóa dữ liệu, nhưng nó chứa các loại do người dùng xác định mà tôi không thể truy cập. Vì vậy, khi tôi deserialize chúng tôi cần phải biết rằng các loại. Tôi nghĩ cách duy nhất để có được quyền truy cập vào chúng là lưu trữ chúng trong một tệp. –

Trả lời

2

Marc Gravell là đúng, có thể bạn nên tuần tự hóa dữ liệu chứ không phải là các loại.

Nhưng vì một lý do nào đó, nếu bạn thực sự muốn sắp xếp theo thứ tự các loại, thì bạn không nên tuần tự hóa đối tượng Kiểu (chắc chắn nó không thể thay thế được). Dù sao, hãy tuần tự hóa Type.FullName để thay thế. Khi bạn tải các loại, sử dụng 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)); 
    } 
} 

Lưu ý: Khi làm việc với bất kỳ Stream (hoặc thực sự bất kỳ IDisposable), bạn phải hoặc là gọi phương thức Dispose hoặc sử dụng câu lệnh using (như tôi đã làm ở trên). Điều này đảm bảo rằng IDisposable được dọn dẹp đúng cách (ví dụ: xử lý Tệp Hệ thống).

+0

Vì một số lý do tôi không thể tìm thấy phương thức Type.Load. Bạn có chắc chắn nó tồn tại? –

+1

Có thể anh ta muốn tuần tự hóa ['Type.AssemblyQualifiedName'] (https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname%28v=vs.110%29.aspx) thay vì' Loại .FullName', để tải loại bằng cách sử dụng ['Type.GetType'] (https://msdn.microsoft.com/en-us/library/w3f99sx1%28v=vs.110%29.aspx) chứ không phải là không tồn tại' Loại.Load' và có lẽ đã được đề xuất sử dụng ['IDataContractSurrogate'] (https://msdn.microsoft.com/en-us/library/system.runtime.serialization.idatacontractsurrogate%28v=vs.110%29. aspx) thay vì tự thay thế các giá trị trước/sau khi tuần tự hóa. – binki