是的,当您第一次添加信息时这可能会很棘手,Version
因为您希望在构造函数中拥有版本号,因此每次调用都被分配其隐式版本,同时每当您反序列化到新的 DTO 时都会使用相同的构造函数。
不幸的是,由于原始 DTO 中没有版本,因此它没有序列化到线路上,因此它永远不会覆盖隐式分配的版本字段。
为了解决这个问题(并在构造函数中保留隐式分配的版本号),您需要有效地重置反序列化中使用的版本。
您可以通过覆盖JsConfig.ModelFactory
on App_Start(即在您的 AppConfig 中)使用 JSON/JSV 序列化程序来执行此操作,这允许您控制为反序列化中使用的每个 POCO 类型创建的实例。
在这种情况下,我们希望将任何具有版本的 DTO 重置为0
没有版本号的 DTO 被分配的方式,而具有版本号的0
DTO 将覆盖它:
JsConfig.ModelFactory = type => {
if (typeof(IHasVersion).IsAssignableFrom(type))
{
return () => {
var obj = (IHasVersion)type.CreateInstance();
obj.Version = 0;
return obj;
};
}
return () => type.CreateInstance();
};
为了简单起见,我在IHasVersion
这里使用了显式接口,但您也可以轻松地使用反射来检测和重新分配包含版本号的类型。
这是一个原始 DTO 的示例,其中没有 Version 属性反序列化为具有隐式分配的版本号的 DTO:
public class Dto
{
public string Name { get; set; }
}
public interface IHasVersion
{
int Version { get; set; }
}
public class DtoV1 : IHasVersion
{
public int Version { get; set; }
public string Name { get; set; }
public DtoV1()
{
Version = 1;
}
}
现在,当您将原始 DTO 反序列化为较新DtoV1
的 DTO 时,它保留为 0:
var dto = new Dto { Name = "Foo" };
var fromDto = dto.ToJson().FromJson<DtoV1>();
fromDto.Version // 0
fromDto.Name // Foo
如果您使用新的 DTO,它会填充版本号:
var dto1 = new DtoV1 { Name = "Foo 1" };
var fromDto1 = dto1.ToJson().FromJson<DtoV1>();
fromDto.Version // 1
fromDto.Name // Foo 1