views:

161

answers:

2

I'm trying to use the XmlSerializer to persist a List(T) where T is an interface. The serializer deos not like interfaces. I'm curious if there is a simple way to serialize a list of hetrogenous objects easily with XmlSerializer. Here's what I'm going for:

        public interface IAnimal
    {
        int Age();
    }
    public class Dog : IAnimal
    {
        public int Age()
        {
            return 1;
        }
    }
    public class Cat : IAnimal
    {
        public int Age()
        {
            return 1;
        }
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        var animals = new List<IAnimal>
        {
            new Dog(),
            new Cat()
        };

        var x = new XmlSerializer(animals.GetType());
        var b = new StringBuilder();
        var w = XmlTextWriter.Create(b, new XmlWriterSettings { NewLineChars = "\r\n", Indent = true });
        //FAIL - cannot serialize interface. Does easy way to do this exist?
        x.Serialize(w, animals);
        var s = b.ToString();    
    }
+1  A: 

Do you have to use XmlSerializer? This is a known issue with XmlSerializer.

You can use BinaryFormatter to save to a stream:

BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, animals);

Other alternative is to use WCF's DataContractSerializer and provide types using KnownType attribute.

Aliostad
I forgot to mention that its required to be text so I can edit manually if need be, so the binary does not work. The DataContractSerializer looks nice, but I looked around and did not see an example of serializing a list of mixed type using it. Thanks!
Steve
+2  A: 

You can use XmlSerializer as well, but you need to include all the possible types that can appear in the object graph you're serializing, which limits extensibility and lowers maintainability. You can do it by using an overload of the constructor of XmlSerializer:

var x = new XmlSerializer(animals.GetType(), new Type[] { typeof(Cat), typeof(Dog) });

Also, there are several issues of note when using XmlSerializer, all of the outlined here (MSDN) - for example look under the heading 'Dynamically generated assemblies'.

Alex Paven
I did try this but XmlSerializer still failed because the 'interface cannot be serialized'. I did not know this ctor for XmlSerializer, learned something new, thanks.
Steve