2014-07-14 151 views
6

我有一個類型列表,我需要保存到文件並在其後讀取它。 我用DataContractSerializer,但我反序列化期間得到一個異常:序列化/反序列化System.RuntimeType

無法找到與參數(SerializationInfo中, 的StreamingContext)在ISerializable的 「System.RuntimeType」 構造。

我已經添加System.RuntimeType作爲我的序列化程序的已知類型,但它沒有幫助。

這裏是我的兩個方法的代碼

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

序列化似乎做工精細,輸出文件是好的,但在反序列化問題開始:

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 
    } 

有什麼辦法去通過這個?或者也許有其他方式來存儲類型?

+3

您應該序列化數據**,而不是執行。 「類型」是關於實現的100%。坦率地說,這只是錯誤的路要走,並且幫助你進一步走下那條黑暗的道路將是一種傷害。 IMO。 –

+0

我會序列化數據,但它包含我無法訪問的用戶定義類型。所以當我反序列化他們時,我需要知道這些類型。我認爲訪問它們的唯一方法是將它們存儲在一個文件中。 –

回答

2

Marc Gravell是對的,你可能應該序列化數據而不是類型。

但由於某種原因,如果你真的想序列化類型本身,那麼你不應該序列化類型對象(很確定它不是可以分段的)。無論如何,請改爲序列化Type.FullName。當加載類型,使用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)); 
    } 
} 

注:當任何Stream(或任何真正的IDisposable)的工作,你必須要麼調用Dispose方法或使用using語句(如我上面做的)。這確保IDisposable已被正確清理(即釋放文件系統句柄)。

+0

出於某種原因我無法找到Type.Load方法。你確定它存在嗎? –

+1

他可能是爲了序列化['Type.AssemblyQualifiedName'](https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname%28v=vs.110%29.aspx)而不是'Type .FullName',用['Type.GetType'](https://msdn.microsoft.com/en-us/library/w3f99sx1%28v=vs.110%29.aspx)加載該類型,而不是不存在的' Type.Load',並應該可能建議使用['IDataContractSurrogate'](https://msdn.microsoft.com/en-us/library/system.runtime.serialization.idatacontractsurrogate%28v=vs.110%29。 aspx)而不是在序列化之前/之後手動替換值。 – binki