如何设计一个版本转换器(Json.net),它可以将一个非常旧的版本处理到一个没有太多代码污点的新版本

时间:2012-11-16 09:33:56

标签: class serialization architecture versioning json.net

我的要求是创建一个高效的版本转换器设计。让我们假设每个版本都演变了以下类。

//版本1

    internal class PatientV1
    {
        public string FullName { get; set; }
        public string PatientNr { get; set; }
        public GenderV1 Gender { get; set; }
    }

    internal enum GenderV1
    {
        MALE,
        FEMALE
    }

//版本2

    internal class PatientV2
    {
        public Name FullName { get; set; }
        public string PatientNr { get; set; }
        public GenderV2 Gender { get; set; }
    }

    internal class Name
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Title { get; set; }
    }

    internal enum GenderV2
    {
        MALE,
        FEMALE,
        UNKNOWN
    }

//版本3

    internal class PatientV3
    {
        public IPerson Person { get; set; }
        public string PatientNr { get; set; }
    }

    internal interface IPerson
    {
        Name Name { get; set; }
        GenderV3 Gender { get; set; }
    }


    internal class Person : IPerson
    {
        public Name Name { get; set; }
        public GenderV3 Gender { get; set; }
    }


    internal enum GenderV3
    {
        MALE,
        FEMALE,
        MALE_TO_FEMALE_CONVERSION_INPROGRESS,
        FEMALE_TO_CONVERSION_INPROGRESS,
        UNKNOWN
    }

我创建了JsonConverter,将一个版本反序列化为另一个版本。这增加了许多转换器组合((n-1)!),例如。

  1. PatientV1ToV2Converter从版本1转换为版本2
  2. PatientV1ToV3Converter将从版本1转换为版本3
  3. PatientV2ToV3Converter将从版本2转换为版本3
  4. 因此,我希望PatientV1ToV3Converter呼叫PatientV1ToV2Converter将患者从PatientV1带到PatientV2,然后PatientV1ToV3Converter在PatientV2上工作,使其成为PatientV3。

    所有这些我想做的就是没有任何旧版本的患者(PatientV1和PatientV2)出现在申请目录中。

    任何设计,无论是否有较旧的dll限制,我都可以。

2 个答案:

答案 0 :(得分:2)

我在项目中做了类似的事情

我已经设置了

serializerSettings.Converters = new List<JsonConverter>() { new MyAppVersionConverter() };

在此MyAppVersionConverter中,我已覆盖ReadJson并编写以下代码

JObject jObjectV = JObject.Load( reader );
//Get the type information from JObject by getting the "$type" property and strip it to get the version
string objectVersion = GetVersion(jObjectV.GetValue("$type"));

现在通过添加或删除属性来修改现有的jObjectV以转换为所需的版本,然后

e.g。从我的代码

JProperty firstNameProp = new JProperty( "FirstName", firstName );
JProperty lastNameProp = new JProperty( "LastName", lastName );
JProperty typeProperty = new JProperty( "$type", "MyDetailV2.EmployeeDetail, MyDetailV2, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" );

JObject jObjectV2 = new JObject();
jObjectV2.Add( typeProperty );
jObjectV2.Add( firstNameProp );
jObjectV2.Add( lastNameProp );

return jObjectV2.ToObject<EmployeeDetail>();

我还在改进。一旦我做了完整的改变,我将发布。

如果您在这方面有任何问题,请告诉我

答案 1 :(得分:0)

你的方法很健全。其他一些项目也在使用类似的方法来处理升级。

例如,MythTV项目使用相同的想法如何从任何旧版本实时升级数据库模式。到目前为止,他们已经能够无缝地处理over 300 revisions