C# 列表的序列化<;IMyInterface>;使用ISerializable
谢谢你看 我正在开发一个新版本的产品,该产品已部署在现场。我需要保持从旧软件反序列化现有文件的能力 下面是一个人为的例子: 我有一个现有的客户群,他们需要访问序列化文件。为了回答这个问题,他们有一个“动物园”档案,里面有长颈鹿的名单C# 列表的序列化<;IMyInterface>;使用ISerializable,c#,covariance,iserializable,C#,Covariance,Iserializable,谢谢你看 我正在开发一个新版本的产品,该产品已部署在现场。我需要保持从旧软件反序列化现有文件的能力 下面是一个人为的例子: 我有一个现有的客户群,他们需要访问序列化文件。为了回答这个问题,他们有一个“动物园”档案,里面有长颈鹿的名单 [Serializable] public class Giraffe : ISerializable { public int Age { get; private set; } public Giraffe(int age) {
[Serializable]
public class Giraffe
: ISerializable
{
public int Age { get; private set; }
public Giraffe(int age)
{
Age = age;
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Age", Age);
}
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
private Giraffe(SerializationInfo info, StreamingContext context)
{
Age = info.GetInt32("Age");
}
}
现在,我们正在部署一个新版本的“Zoo”软件,我们将支持长颈鹿以外的动物,我们本来应该这样做的,但由于时间限制,我们不得不发布1.0版,只有长颈鹿功能集
public interface IAnimal
{
int Age { get; }
}
[Serializable]
public class Animal
: IAnimal,
ISerializable
{
public int Age { get; private set; }
public Animal (int age)
{
Age = age;
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Age", Age);
}
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
private Animal(SerializationInfo info, StreamingContext context)
{
Age = info.GetInt32("Age");
}
}
我正在使用一个定制的序列化活页夹将老长颈鹿反序列化为动物
public class LegacyZooSerializationBinder
: SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
if (typeName.StartsWith("Test.Giraffe"))
return typeof(Animal);
else if (typeName.StartsWith("System.Collections.Generic.List`1[[Test.Giraffe"))
return typeof(List<Animal>);
else return null;
}
}
如有任何建议,将不胜感激。我很难在这类事情上找到好的资源。谢谢 考虑一次性将旧文件转换为新格式,最好在安装时进行转换,备份后再进行转换。这样,您就不必永远支持这种奇怪的一次性序列化,您的代码库也会变得非常简单。+1表示“仅长颈鹿功能集”。我很喜欢。你有没有考虑过在安装时做一次长颈鹿到动物的转换(当然有备份),以避免你因长颈鹿特例的永久性维护而头疼?克里斯,我没有考虑过一次转换。很明显,它会把代码中的东西清理得干干净净。我更愿意让它对用户透明,特别是因为它是后端更改。如果所有其他方法都失败了,这可能是一个非常好的解决方案。好吧,好吧,我会把它作为一个答案,以防你最终走上那条路
[Serializable]
public class Zoo
: ISerializable,
IDeserializationCallback
{
List<IAnimal> m_List = null;
List<Giraffe> m_LegacyList = null; //Just so that we can save an old-style zoo
//Temp copy of the list
List<Animal> m_List_Deserialization_Temp_Copy = null;
public Zoo(bool legacy)
{
m_List = new List<IAnimal>();
if (legacy)
{
//Create an old style zoo, just for the example
m_LegacyList = new List<Giraffe>();
m_LegacyList.Add(new Giraffe(0));
m_LegacyList.Add(new Giraffe(1));
}
else
{
m_List.Add(new Animal(0));
m_List.Add(new Animal(1));
}
}
public List<IAnimal> List
{
get { return m_List; }
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
if(m_LegacyList != null) //Save as an old style list if we have old data
info.AddValue("list", m_LegacyList);
else
info.AddValue("list", m_List);
}
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
private Zoo(SerializationInfo info, StreamingContext context)
{
try
{
//New style
m_List = (List<IAnimal>)info.GetValue("list", typeof(List<IAnimal>));
}
catch (InvalidCastException)
{
//Old style
//Put it in a temp list, until the OnDeserialization callback is called, this will be a list, full of null items!
m_List_Deserialization_Temp_Copy = (List<Animal>)info.GetValue("list", typeof(List<Animal>));
}
}
void IDeserializationCallback.OnDeserialization(object sender)
{
if (m_List_Deserialization_Temp_Copy != null)
{
m_List = new List<IAnimal>();
//This works because IEnumerable<Animal> is covariant to IEnumerable<IAnimal>
m_List.AddRange(m_List_Deserialization_Temp_Copy);
}
}
}
static void Main(string[] args)
{
{
var item = new Zoo(false);
var formatter = new BinaryFormatter();
var stream = new MemoryStream();
formatter.Serialize(stream, item);
stream.Position = 0;
formatter.Binder = new LegacyZooSerializationBinder();
var deserialized = (Zoo)formatter.Deserialize(stream);
Debug.Assert(deserialized.List.Count == 2);
Debug.Assert(deserialized.List[0] != null);
Debug.Assert(deserialized.List[0].Age == 0);
Debug.Assert(deserialized.List[1] != null);
Debug.Assert(deserialized.List[1].Age == 1);
Console.WriteLine("New-style Zoo serialization OK.");
}
{
var item = new Zoo(true);
var formatter = new BinaryFormatter();
var stream = new MemoryStream();
formatter.Serialize(stream, item);
stream.Position = 0;
formatter.Binder = new LegacyZooSerializationBinder();
var deserialized = (Zoo)formatter.Deserialize(stream);
Debug.Assert(deserialized.List.Count == 2);
Debug.Assert(deserialized.List[0] != null);
Debug.Assert(deserialized.List[0].Age == 0);
Debug.Assert(deserialized.List[1] != null);
Debug.Assert(deserialized.List[1].Age == 1);
Console.WriteLine("Old-style Zoo serialization OK.");
}
Console.ReadKey();
}