1

我正在通过 API 为另一个程序编写插件。为了保存它的当前状态,我的插件将 Project 对象的一个​​实例存储到文件中,方法是将其序列化为 XML 并将其存储在用户字符串中,这是 API 提供的一项功能。它还存储一个单独的字符串,其中包含当前正在使用的插件的版本号。

当用户打开文件时,我的插件会检查版本号。如果当前插件版本与文件中存储的版本不同,则会弹出一条消息,警告用户版本不同,文件可能导致插件崩溃。

我更愿意提供一组迁移脚本,当用户在新版本的插件中打开旧文件时,它们会自动运行。我的问题是这些通常去哪里以及它们是如何组织的?

还说我的 Project 类在尝试从旧文件反序列化项目的版本之间发生了显着变化,新的 Project 类将失败。我不想保留 Project 类的每个版本的副本是我的程序集,但同时必须通过 XML 进行解析会更加痛苦。假设解析 XML 是最好的选择,任何人都可以提出比下面的代码更有条理的方法吗?

public string MigrateProject(int fileVersion, int plugInversion, string proj)
{
    if(fileVersion>plugInversion)
    {
       //tell user to upgrade their copy of the plugin
       return null;
    }

    if(fileVersion ==1)
    { 
        string v2 = Migrate1to2(serializedProject);
        string v3 = Migrate2to3(v2);
        string v4 = Migrate3to4(v3);
        return v4;
    }
    else if(fileVersion ==2)
    { 
        string v3 = Migrate2to3(serializedProject);
        string v4 = Migrate3to4(v3);
        return v4;
    }
    else if(fileVersion ==3)
    { 
        string v4 = Migrate3to4(serializedProject);
        return v4;
    }
    else 
    {
         //could not migrate project message
         return null;
    }
}
4

2 回答 2

1

XmlSerializer 不具有版本容错性,如果您不包含版本字段,您可以在手动进行反序列化时对其进行操作。

BinaryFormatter与 SoapFormatter 和DataContractSerializer一样支持版本。

您仍然需要处理转换,并且可以通过这种方式轻松剪切代码:

if(fileVersion ==1)
{ 
    serializedProject = Migrate1to2(serializedProject);
    fileVersion = 2;
}
if(fileVersion ==2)
{ 
    serializedProject = Migrate2to3(serializedProject);
    fileVersion = 3;
}
if(fileVersion ==3)
{ 
    serializedProject = Migrate3to4(serializedProject);
    fileVersion = 4
}
else 
{
     //could not migrate project message
     return null;
}
于 2009-12-12T21:34:02.393 回答
0

将您的迁移方法存储在如下列表中:

List<Func<string,string>> myMigrateMethods = new List<Func<string,string>>();
myMigrateMethods.Add(Migrate1To2);
myMigrateMethods.Add(Migrate2To3);
myMigrateMethods.Add(Migrate3To4);

然后从适当的方法开始遍历列表:

public string MigrateProject(int fileVersion, int plugInversion, string proj)
{
    if(fileVersion>plugInversion)
    {
       //tell user to upgrade their copy of the plugin
       return null;
    }

    //user already at max version
    if(fileVersion >= (myMigrateMethods.Length-1)) return null;

    var firstMigrateMethodNeeded = (fileVersion-1); //array is 0-based

    var output = serializedProject;
    for(var i= firstMigrateMethodNeeded; i< myMigrateMethods.Length; i++)
    {
       output = myMigrateMethods[i](output);
    }

    return output;

}
于 2009-12-12T21:39:25.893 回答