Shahar
Shahar

Reputation: 161

Serializing interfaces

I'm trying to run code similar to this:

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
    [Serializable]
    [XmlInclude(typeof(List<Class2>))]
    public class Class1
    {
        private IList<Class2> myArray;

        public IList<Class2> MyArray
        {
            get { return myArray; }
            set { myArray = value; }
        }

    }

    public class Class2
    {
        private int myVar;

        public int MyProperty
        {
            get { return myVar; }
            set { myVar = value; }
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            XmlSerializer ser = new XmlSerializer(typeof(Class1), new Type[] { typeof(List<Class2>) });
            FileStream stream = File.OpenWrite("Data.xml");
            ser.Serialize(stream, new List<Class1>());
            stream.Close();
        }
    }
}

Can somebody explain to me what am I doing wrong?

I get a:

Cannot serialize member .. MyArray ... because it is an interface.

Shouldn't the XmlInclude resolve this?

Upvotes: 14

Views: 45124

Answers (4)

brunnerh
brunnerh

Reputation: 184416

Here's an untested shady workaround that i tend to use in principle:

private IList<Class2> myArray;
[XmlIgnore]
public IList<Class2> MyArray
{
    get { return myArray; }
    set { myArray = value; }
}

[XmlElement("MyArray")]
public object MyArraySerializable
{
    get { return MyArray; }
    set { MyArray = value as IList<Class2>; }
}

This will serialize whatever list you may be using as generic object with a type attribute which will tell the deserializer the actual type of the object, so when that object gets deserialized it should be cast to a IList<Class2> again. Remember to provide any types that may be assumed by the interface.


I see no reason why any serializer should be unable to serialize such properties. It is not like you actually try to serialize an interface, you try to serialize an object which implements a certain interface (which is not far different from abstract subclassing, some programming languages even solely operate on interfaces).

When the serializer should serialize that object it knows that the object implements that interface, all it really has to do is serialize it and attach the type attribute (like it does if you serialize abstract classes or just super-classes in general).

Now the deserializer looks at the type and can check if that object in fact implements the required interface and then deserialize it to the respective property.

Upvotes: 18

joniba
joniba

Reputation: 3499

Or use the DataContractSerializer instead.

Upvotes: 12

Martin Hennings
Martin Hennings

Reputation: 16846

You included typeof(List<...>), but MyArray is of type IList<...> which is no apparent data structure itself but more of a placeholder to take some data structure.

Change the type of MyArray to a specific type (as List, e.g.) and it should work.

    private List<Class2> myArray;

    public List<Class2> MyArray
    {
        get { return myArray; }
        set { myArray = value; }
    }

Upvotes: 0

John Saunders
John Saunders

Reputation: 161773

No. You can't serialize an interface. Ever. It just told you that.

An interface is nothing more than a description of a set of behaviors. It says nothing about the contents of an instance. In particular, although an instance of a class implementing an interface must implement all of its members, it will certainly have properties of its own which need to be serialized.

How would it be deserialized?

What class would be used to deserialize the interface on the other side?

Upvotes: 18

Related Questions