Cant deserilize derived class. But it works if it's in a list or a dictionary. Any thoughts?
Asked Answered
P

1

0

I got a weird problem where I can serialize a derived class if I put it in a List but not when it stands on it own.

I am using these methods to serialize and deserialize (found them here):

    public static string Serialize(T obj)
    {
        using (MemoryStream memoryStream = new MemoryStream())
        using (StreamReader reader = new StreamReader(memoryStream))
        {
            DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
            serializer.WriteObject(memoryStream, obj);
            memoryStream.Position = 0;
            return reader.ReadToEnd();
        }
    }

    public static T Deserialize(string xml, Type toType)
    {
        using (Stream stream = new MemoryStream())
        {
            byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
            stream.Write(data, 0, data.Length);
            stream.Position = 0;
            DataContractSerializer deserializer = new DataContractSerializer(toType);
            return (T)deserializer.ReadObject(stream);
        }
    }

I have a base class Entity. And a derived class Thing.

[DataContract]
[KnownType(typeof(Thing))]
Class Entity
{
}

[DataContract]
Class Thing : Entity
{
}

Now, when I try to serialize an object instantiated as Thing there is no problem but the deserialization gives an error.

            Thing e = new Thing();
            string xmlstring = XML<Entity>.Serialize(e); 

            Entity testE = XML<Entity>.Deserialize(xmlstring, typeof(Entity));

The error says something like Expected element Entity from ... . Element Thing was found. (Was not written in english.)

But the weird thing is that it works if I put the object into a list and serialize-deserialize the list.

            Thing e = new Thing();
            List<Entity> test = new List<Entity>();
            test.Add(e);

            var xmlstring = XML<List<Entity>>.Serialize(test);

            List<Entity> test2 = XML<List<Entity>>.Deserialize(xmlstring, typeof(List<Entity>));

Now test2 has an entry with the a correct Thing-item. Even if this could be a workaround it surely must be an easier way and it must be something that would be easy to fix I think? Any thoughts? What did I miss?

(And of course it works when deserializing my Thingobject as a Thing-object but that's not what I want, when deserializing I will not know the class on beforehand.)

Pigmentation answered 1/8, 2017 at 16:31 Comment(3)
tl:dr - you are trying to deserialize a child type (thing) to a base type (entity)., without defining what T on the serialize method. This post may help. #43675752Expressman
@Jaya, I saw that question too, but it seems not to handle DataContract-serialization. And the answer is target to a specific base(?) class not a generic class.Pigmentation
@Jaya, Your without defining what T on the serialize method got me to try to modify the serialize-method to have it accept a second ´typeof(Entity)` argument, and use that instead of GetType() -method. It worked!Pigmentation
P
0

Seems that I have found a workaround myself after thinking about @Jaya's comment. I modified the serialize method to force it to serialize to the base class type. Originally I did not think this would work, but it did!

public static string Serialize(T obj, Type toType)
{
    using (MemoryStream memoryStream = new MemoryStream())
    using (StreamReader reader = new StreamReader(memoryStream))
    {
        DataContractSerializer serializer = new DataContractSerializer(toType);
        serializer.WriteObject(memoryStream, obj);
        memoryStream.Position = 0;
        return reader.ReadToEnd();
    }
}
Pigmentation answered 1/8, 2017 at 17:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.