组织文件版本迁移代码的最佳方法是什么?

时间:2009-12-12 21:23:17

标签: c# .net migration versioning data-migration

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

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

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

另外说我的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;
    }
}

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分: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;

}