BillWoodruff
Позвольте мне привести вам рабочий пример, чтобы доказать, что экземпляры интерфейсов могут быть сериализованы. Обратите внимание, что когда я говорю "экземпляры интерфейсов", я имею в виду, что вы взяли допустимые экземпляры некоторого класса, унаследованного от интерфейса, и привели эти экземпляры в их "форму интерфейса". естественно, когда вы сохраняете некоторый "экземпляр интерфейса", подобный этому, вы не сохраняете элементы класса (поля, свойства), которые не указаны в интерфейсе.
Надуманный пример, демонстрирующий задействованные техники; чтобы сделать это "более интересным ... для меня", я также продемонстрирую, как сериализовать статический член статического класса (нет, вы не можете сериализовать сам статический класс):
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);
}
}
Обратите внимание, что каждый раз, когда вы добавляете экземпляр класса 'new Dog или Cat', их конструкторы добавляют ссылку на новый класс в две статические коллекции (универсальные списки) в статическом классе с именем ' MyAnimals. Новая собака или кошка экземпляр добавляется в список 'вид животного, но и список 'тип IAnimal.
Итак, допустим, вы создаете несколько экземпляров этой структуры классов:
// in some Method or EventHandler
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"));
Что вам нужно сделать, чтобы сериализовать и де-сериализовать список экземпляров Cat и Dog, хранящихся в их 'IAnimal форме в статическом классе 'MyAnimals:
public static class SaveTheAnimals
{
private static DataContractSerializer _dcs;
public static string filePath = @"C:\Users\YourUserName\Desktop\test\SomeAnimals.xml";
public static void SerializeMyAnimals()
{
// see note below
_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;
}
}
Записи:
1. Что делает эту "работу", так это предоставление новому экземпляру сериализатора DataContract списка "известных типов" для его работы. Вы заметите, что вы также можете украсить класс DataContract атрибутом 'KnownType для каждого типа, о котором вы хотите, чтобы он был "осведомлен" ... впрочем, в данном случае ... статический класс ... это не сработает (не спрашивайте меня, почему) ... и вы должны предоставить список известных типов сериализатору при его создании.
2. Посмотрите на фактический XML, полученный при сохранении списка<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>
Обратите внимание, что каждая запись содержит не только имя вида, которое вы ожидаете, но и информацию о 'DogName или 'CatName. И, пожалуйста, спросите Microsoft, почему это работает :) потому что если вы приведете конкретную "собаку" или "кошку" к ее животной форме, вы не должны видеть эту информацию.