Let me give you a working example to prove that instances of Interfaces can be serialized. Note that when I say "instances of Interfaces" I mean you have taken valid instances of some Class that inherited from an Interface and cast those instances into their "Interface Form." Naturally, when you save some "interface instance" like this, you do not save the elements of the Class (Fields, Properties) that are not specified in the Interface.
A contrived example demonstrating the techniques involved; to make this "more interesting ... for me", I will also demonstrate how to serialize a static Member of a Static Class (no, you cannot serialize a Static Class itself):
namespace YourNameSpace
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
public interface IAnimal
{
Species AnimalSpecies { set; get; }
}
public interface ISpecies
{
string SpeciesName { set; get; }
}
[DataContract]
public class Species : ISpecies
{
[DataMember]
public string SpeciesName { get; set; }
public Species(string speciesName)
{
SpeciesName = speciesName;
}
}
[DataContract]
public class Animal : IAnimal
{
[DataMember]
public Species AnimalSpecies { set; get; }
public Animal(string speciesName)
{
AnimalSpecies = new Species(speciesName);
}
}
[DataContract]
public class Dog : Animal
{
[DataMember]
public string DogName { set; get; }
public Dog(string dogName, string speciesName) : base(speciesName)
{
DogName = dogName;
}
}
[DataContract]
public class Cat : Animal
{
[DataMember]
public string CatName { set; get; }
public Cat(string speciesName, string catName) : base(speciesName)
{
CatName = catName;
}
}
[DataContract]
public static class MyAnimals
{
[DataMember]
public static List<Animal> TheAnimals { set; get; }
[DataMember]
public static List<IAnimal> TheIAnimals { set; get; }
static MyAnimals()
{
TheAnimals = new List<Animal>();
TheIAnimals = new List<IAnimal>();
}
}
[DataContract]
public class MyCats
{
[DataMember]
private List<Cat> MyCatCollection { set; get; }
public MyCats()
{
MyCatCollection = new List<Cat>();
}
public void AddCat(Cat theCat)
{
MyCatCollection.Add(theCat);
MyAnimals.TheAnimals.Add(theCat);
MyAnimals.TheIAnimals.Add(theCat);
}
}
[DataContract]
public class MyDogs
{
[DataMember]
private List<Dog> MyDogCollection { set; get; }
public MyDogs()
{
MyDogCollection = new List<Dog>();
}
public void AddDog(Dog theDog)
{
MyDogCollection.Add(theDog);
MyAnimals.TheAnimals.Add(theDog);
MyAnimals.TheIAnimals.Add(theDog);
}
}
Note that every time you add a 'new Dog or Cat Class instance their constructors add the reference to the new Class to two static collections (generic lists) in a static Class named 'MyAnimals. The new Dog or Cat instance is added to a list of the 'Animal Type, and a list of the 'IAnimal Type.
So let's say you create some instances of this Class structure:
MyCats myCats = new MyCats();
myCats.AddCat(new Cat("felix", "HisRoyalMeow"));
myCats.AddCat(new Cat("felix", "HerRoyalMeow"));
MyDogs myDogs = new MyDogs();
myDogs.AddDog(new Dog("Lab", "LikesToBeWet"));
myDogs.AddDog(new Dog("Chihuahua", "Mr. Sausage"));
What you need to do to serialize and de-serialize the List of instances of Cat and Dog stored in their 'IAnimal form in the static Class 'MyAnimals:
public static class SaveTheAnimals
{
private static DataContractSerializer _dcs;
public static string filePath = @"C:\Users\YourUserName\Desktop\test\SomeAnimals.xml";
public static void SerializeMyAnimals()
{
_dcs = new DataContractSerializer(typeof(List<IAnimal>), new List<Type>{typeof(Cat), typeof(Dog)});
using (FileStream fs = new FileStream(filePath, FileMode.Create))
{
_dcs.WriteObject(fs, MyAnimals.TheIAnimals);
}
}
public static List<IAnimal> DeSerializeMyAnimals()
{
_dcs = new DataContractSerializer(typeof(List<IAnimal>), new List<Type> { typeof(Cat), typeof(Dog) });
List<IAnimal> myAnimals;
using (FileStream fs = new FileStream(filePath, FileMode.Open))
{
myAnimals = (List<IAnimal>)_dcs.ReadObject(fs);
}
return myAnimals;
}
}
Notes:
1. What makes this "work" is providing the new instance of the DataContract Serializer a list of "known Types" for it to work with. You will note that you can also decorate a DataContract Class with the 'KnownType Attribute for each Type you wish it to be "aware of" ... however, in this case ... a Static Class ... that would not work (don't ask me why) ... and you must provide the list of Known Types to the serializer when you construct it.
2. Look at the actual XML produced by saving the List<IAnimal>
<ArrayOfanyType xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<anyType i:type="a:Cat" xmlns:a="http://schemas.datacontract.org/2004/07/June6AutoForm">
<a:AnimalSpecies>
<a:SpeciesName>felix</a:SpeciesName>
</a:AnimalSpecies>
<a:CatName>HisRoyalMeow</a:CatName>
</anyType>
<anyType i:type="a:Cat" xmlns:a="http://schemas.datacontract.org/2004/07/June6AutoForm">
<a:AnimalSpecies>
<a:SpeciesName>felix</a:SpeciesName>
</a:AnimalSpecies>
<a:CatName>HerRoyalMeow</a:CatName>
</anyType>
<anyType i:type="a:Dog" xmlns:a="http://schemas.datacontract.org/2004/07/June6AutoForm">
<a:AnimalSpecies>
<a:SpeciesName>LikesToBeWet</a:SpeciesName>
</a:AnimalSpecies>
<a:DogName>Lab</a:DogName>
</anyType>
<anyType i:type="a:Dog" xmlns:a="http://schemas.datacontract.org/2004/07/June6AutoForm">
<a:AnimalSpecies>
<a:SpeciesName>Mr. Sausage</a:SpeciesName>
</a:AnimalSpecies>
<a:DogName>Chihuahua</a:DogName>
</anyType>
</ArrayOfanyType>
Note that each entry contains not only the SpeciesName, which you would expect, but, also, the 'DogName or 'CatName information. And, please ask Microsoft why this works :) because if you cast a specific 'Dog or 'Cat to its IAnimal Form, you should not see that information.