Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serialize/deserialize System.RuntimeType

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?

like image 805
Nick Tarasov Avatar asked Jul 14 '14 11:07

Nick Tarasov


People also ask

What is serialize vs deserialize?

Serialization is a mechanism of converting the state of an object into a byte stream. Deserialization is the reverse process where the byte stream is used to recreate the actual Java object in memory.

How many types of serialization are there in C#?

Basic and custom serialization Binary and XML serialization can be performed in two ways, basic and custom.

Can you serialize an abstract class C#?

Thanks! Well, no, because you can only serialize objects, and you can't create an instance of an abstract class.


1 Answers

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).

like image 185
Philip Pittle Avatar answered Oct 20 '22 14:10

Philip Pittle