2014-07-14 122 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