1

I'm having quite the problem with my XML serialization issue. I've been working on my project to (de) serialize an object that has an interface as an attribute. I know that you can't serialize an interface and that is what my error tells me.

Here is an example of the object that I want to save to a file:

public class Task
{
    public int id;
    public string name;
    public TypeEntree typeEntree;
    public int idRequired;
    public string code;
    public int waitTime;
    public string nameApp;
    // ... Constructors (empty and non-empty) and methods ...
}

TypeEntree is an empty interface, it's only to relate different objects and use them easily around my application. For instance, here are two of the objects that uses this interface:

[Serializable]
public class Mouse : TypeEntree
{
    public Point point;
    public IntPtr gaucheOuDroite;
    public string image;
    // ... Constructors (empty and non-empty) and methods ...
}

[Serializable]
public class Sequence : TypeEntree
{
    public List<Tuple<string, Point, long, IntPtr>> actions;
    // ... Constructors (empty and non-empty) and methods ...
}

The interface TypeEntree also has the [Serializable] attribute and also the [XmlInclude (typeof (Mouse)] for each of my classes that uses this interface.

Here is my question: Why does when I try to serialize, it cannot detects the type of my object (typeEntree in Task) since I added the [XmlInclude (typeof (Mouse)] attributes?

Also, how should I fix this issue?

Additionnally, here are the methods of serializing/deserializing I found that seems to works very well without interface: https://stackoverflow.com/a/22417240/6303528

Community
  • 1
  • 1
  • which serializer do you use? – rene May 07 '16 at 10:30
  • In the last sentence I specify it. http://stackoverflow.com/a/22417240/6303528 - XML XmlSerializer – SacDeFromage May 07 '16 at 10:36
  • The serializer add the attributes not for serializing, but fore de-serializing. The net library need the attributes when deserializing to distinguish between the inherited classes. – jdweng May 07 '16 at 14:52
  • You can't serialize an interface with `XmlSerializer` even if you add `XmlInclude`. See [XML serialization of interface property](https://stackoverflow.com/questions/1333864) or [Serializing interfaces](https://stackoverflow.com/questions/4659248). [`XmlInclude`](https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlincludeattribute.aspx) is for base class/derived class hierarchies. – dbc May 07 '16 at 18:12
  • Incidentally, if I change `TypeEntree` to be a `public abstract class`, your types still can't be serialized because `IntPtr` can't be serialized directly. As a workaround you could use a `long` proxy property. See [Serialize an IntPtr using XmlSerializer](https://stackoverflow.com/questions/3472509/serialize-an-intptr-using-xmlserializer). – dbc May 07 '16 at 18:15
  • Thank you for your links, I'll be working on it and updating soon. @dbc – SacDeFromage May 07 '16 at 21:32
  • Watch out for `Tuple` as well. See [Why I could not serialize a tuple in C#?](https://stackoverflow.com/questions/13739348/why-i-could-not-serialize-a-tuple-in-c) and [Tuple cannot be serialized because it does not have a parameterless constructor](https://stackoverflow.com/questions/33225824) – dbc May 07 '16 at 21:41
  • Thank you for your help, It was actually related to everything you said! I'll do a response to update what I had wrong and how I fixed it. Thank you so much, it's working now :). I still have to figure out how to deserialize it, but it's a huge chunk! @dbc – SacDeFromage May 07 '16 at 22:05
  • @dbc yes it's exactly what I meant. – SacDeFromage May 07 '16 at 22:09

1 Answers1

1

Thanks to @dbc links in the comments of my first questions, I was able to figure out every problem. Here is what I did :

My interface TypeEntree became an abstract class.

[Serializable]
[XmlInclude(typeof(Mouse))]
[XmlInclude(typeof(Keyboard))]
[XmlInclude(typeof(Sequence))]
public abstract class TypeEntree
{
}

Also, the Mouse class had an IntPtr, which is not serializable. I had to convert it to an Int64 (a long). Source is both from @dbc comments and here : Serialize an IntPtr using XmlSerializer

Finally, a Tuple cannot be serialized since it does not have a parameterless constructor. A fix to this is simply change the type of the Tuple to the class I created (TupleModifier) following this example : https://stackoverflow.com/a/13739409/6303528

public class TupleModifier<T1, T2, T3, T4>
{
    public T1 Item1 { get; set; }
    public T2 Item2 { get; set; }
    public T3 Item3 { get; set; }
    public T4 Item4 { get; set; }

    public TupleModifier() { }

    public static implicit operator TupleModifier<T1, T2, T3, T4>(Tuple<T1, T2, T3, T4> t)
    {
        return new TupleModifier<T1, T2, T3, T4>()
        {
            Item1 = t.Item1,
            Item2 = t.Item2,
            Item3 = t.Item3,
            Item4 = t.Item4
        };
    }

    public static implicit operator Tuple<T1, T2, T3, T4>(TupleModifier<T1, T2, T3, T4> t)
    {
        return Tuple.Create(t.Item1, t.Item2, t.Item3, t.Item4);
    }
}

and to use it in the Sequence class like it was used :

public List<TupleModifier<string, Point, long, long>> actions;
Community
  • 1
  • 1