【问题标题】:XmlSerializer - Best way to migrate a xml file to a new versionXmlSerializer - 将 xml 文件迁移到新版本的最佳方法
【发布时间】:2014-05-12 05:16:03
【问题描述】:

假设我有一个简单的类

public class Document
{
    public int Version { get; set; }
    public string Name { get; set; }
    public string Image { get; set; } // Base64 coded Bitmap object
}

现实世界的对象要复杂得多。我使用XmlSerializer.Serialize 将实例保存到文件中。

图像的内容是这样生成的:

byte[] result = null;
using (var image = Bitmap.FromFile(@"filename"))
using (var stream = new MemoryStream())
{
    image.Save(stream, ImageFormat.Jpeg);
    result = stream.ToArray();
}
var content = Convert.ToBase64String(result);

现在我有一个重大变化。 将来我想保存原始图像数据(也为base64)而不将其转换为jpg。

所以我的新对象将如下所示:

public class Document
{
    public int Version { get; set; }
    public string Name { get; set; }
    public string RawImageString { get; set; }
}

幸运的是,我已经存储了一个版本属性(当前为每个 xml 文件的1)。对于新项目,我可以

现在我想知道是否有任何best practices 关于如何处理模型更改。 我正在考虑这种方法:

  • 仍然在我的类中定义一个属性ImageString,标记为已过时。
  • 该属性将只有一个 setter 而没有 getter
  • 如果设置了ImageString,我只需更新RawImageString

    public class Document
    {
        public int Version { get; set; }
        public string Name { get; set; }
        public string RawImageString { get; set; }
        [Obsolete("Use RawImageString instead")]
        public string ImageString
        { 
            set
            {
                this.RawImageString = value; 
                this.Version = 2;
            }
        }
    }
    

这应该可以很好地工作,但它需要我将旧资产维护到永远。我更喜欢

// depending on the version property XmlSerializer should return a 
// different Document implementation
var serializer = new XmlSerializer(typeof(IDocument));
var document = (IDocument)serializer.Deserialize(reader);

当然,我可以使用工厂方法来实现这一点,但这需要两次读取。一个用于版本,第二个用于具体结果。

【问题讨论】:

  • 最佳实践是逐步进行,而不是在整个代码中强制进行大量级联重构。看起来你已经正确地做到了。
  • 您不将其设为位图对象的字节数组的任何特殊原因。 [XmlElementAttribute("RawImage", DataType = "base64Binary")] public byte[] RawImage { get;放; }
  • @linodh - 好建议,一开始没有考虑到这一点。事不宜迟,以后可能有用。谢谢。

标签: c# .net xml serialization xmlserializer


【解决方案1】:

最终我以这种方式解决了它。

Document 无论如何都是使用静态方法创建的。 现在我检查版本是否与当前版本匹配,如果不匹配则开始迁移。

    public const int CURRENT_VERSION = 2;
    public static DocumentOpen(string path)
    {
        var controller = new DocumentController();

        var item = controller.ReadXml(path);

        if (item.Version != CURRENT_VERSION)
        {
            var migrator = new DocumentMigrator(item, path);
            migrator.MigrateToLatestVersion();
        }

        return item;
    }

迁移器长这样

public class DocumentMigrator
{

    private Document item;
    private String path;

    public DocumentMigrator(Documentitem, string path)
    {
        this.item = item;
        this.path = path;
    }

    public void MigrateToLatestVersion()
    {
        Migrate(Document.CURRENT_VERSION);
    }

    public void Migrate(int to)
    {
        Migrate(item.Version, to);
    }

    private void Migrate(int from, int to)
    {
        if (from < to)
        {
            while (item.Version < to)
                Up(item.Version + 1);
        }
        else if (from > to)
        {
            while (item.Version < to)
                Down(item.Version - 1);
        }
    }

    private void Down(int version)
    {
        throw new NotImplementedException();
    }

    private void Up(int version)
    {
        if (version == 2)
        {
            var stream = File.OpenRead(path);
            var serializer = new XmlSerializer(typeof(DocumentV1));
            var document = (DocumentV1)serializer.Deserialize(stream);

            this.item.RawImageString = document.ImageString;
        }
        else
        {
            throw new NotImplementedException();
        }

        this.item.Version = version;
    }

}

public class DocumentV1
{
    public string ImageString { get; set; }
}

我的想法是我创建了一个助手类DocumentV1,它只包含我想要迁移的属性。这甚至可以通过使用动态或 XElement 来避免。

我执行升级并从原始类更新版本。向后迁移也可以在 Down 方法中实现,但目前不需要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    • 2013-08-28
    相关资源
    最近更新 更多