Reputation: 101
I've got a List of Types that I need to save to file and read it after.
I use DataContractSerializer
but I get an exception during deserialization:
Can't find constructor with arguments (SerializationInfo, StreamingContext) in ISerializable "System.RuntimeType".
I've added System.RuntimeType
as a known type to my serializer, but it didn't help.
Here's code of my two methods
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 seems to work fine, and the output file is ok, but problem starts on 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
}
Is there any way to go through this? Or maybe there's some other way to store types?
Upvotes: 7
Views: 2547
Reputation: 12295
Marc Gravell is right, you probably should be serializing the data and not the types.
But for some reason, if you really want to serialize the types themselves, then you shouldn't serialize the Type object (pretty sure it's not serailizable). Anyway, serialize Type.FullName
instead. When you load the Types, use 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())
}
public 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));
}
}
Note: When working with any Stream
(or really any IDisposable
) you have to either call the Dispose
method or use the using
statement (as I did above). This ensures that the IDisposable
is properly cleaned up (ie releases File System handles).
Upvotes: 3