6

我有这门课

[Serializable]
public class myClass() : ISerializable
{
    public int a;
    public int b;
    public int c;

    public void GetObjectData(SerializationInfo info, 
                              StreamingContext context)
        {
        // Some code
        }

    public myClass(SerializationInfo info, 
                   StreamingContext context)
        {
        // Some code
        }
}

我的数据库中有数百个这样的对象。我现在准备发布我的应用程序的新版本,该类已演变为

[Serializable]
public class myClass() : ISerializable
{
    public int a;
    public string b;
    public int c;
    public bool d;

    public void GetObjectData(SerializationInfo info, 
                              StreamingContext context)
        {
        // Some code
        }

    public myClass(SerializationInfo info, 
                   StreamingContext context)
        {
        // Some code
        }
}

如何使用第二个版本的反序列化构造函数反序列化基于第一个版本序列化的对象。

是否还有未来版本校对我的第二个版本的策略?

4

2 回答 2

4

如果您没有准备,您可能需要求助于 hack:当您的public myClass反序列化构造函数获取 的值时bool d,将代码包含在try/中,并在捕获异常时catch设置为其默认值。d

将来,添加一个int"__ver"(或任何其他不与您传递给的参数冲突的名称info.AddValue),并将其设置为您在类中维护的常量,以指示序列化中的兼容和不兼容更改:

public class myClass : ISerializable {
    private const int __ver = 4;
    public int a;
    public string b;
    public int c;
    public bool d;

    public void GetObjectData(SerializationInfo info, 
                          StreamingContext context) {
        info.AddValue("__ver", ver);
        info.AddValue("a", a);
        // and so on
    }

    public myClass(SerializationInfo info, 
               StreamingContext context) {
        switch(info.GetInt32("__ver")) {
            case 3: 
                // Deserialize prior version
            break;
            case 4: 
                // Deserialize current version
            break;
        }
    }
}
于 2012-04-19T23:00:28.310 回答
2

可序列化的类非常适合通过相同版本的软件传递它们,但是当使用它进行持久性时,您很快就会遇到这个问题。如果您要将对象存储为BLOB,则可以使用protobuf-net 之类的东西,它通过允许可选字段来允许序列化版本控制。

鉴于您当前的困境,您可以做的就是立即尝试使用新字段,如果它们不存在则默认它们:

protected myClass(SerializationInfo info, StreamingContext context)
{
    c = info.GetInt32("Value_C"); 
    try
    {
        b = info.GetBoolean("Value_B");
    }
    catch (SerializationException)
    {
        b = true;
    }
}
于 2012-04-19T23:23:59.527 回答