我们假设我有一个简单的类
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
,标记为过时。如果设置了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);
当然我可以使用工厂方法实现这一点,但这需要两次读取。一个用于版本,第二个用于具体结果。
答案 0 :(得分:2)
最终我这样解决了。
无论如何,使用静态方法创建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方法中实现,但目前不需要。