Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 列表的序列化<;IMyInterface>;使用ISerializable_C#_Covariance_Iserializable - Fatal编程技术网

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();
    }