3

我已经阅读了@mythz https://stackoverflow.com/a/12413091/1095655的这篇文章,但我的声誉还不够高,无法发表评论

我有一个问题是工作。如果您收到带有版本 1 DTO 的请求,则传输的数据中不存在该版本,因为版本 1 DTO 没有 Version 属性。当 ServiceStack 反序列化请求时,它会创建一个 DTO 对象(版本 3),并将版本设置为 2,并且由于未从传输的数据中接收到版本,因此版本不会像预期的那样覆盖为 0。正如我所看到的,您需要从一开始就在您的 DTO 中实施 Version,否则它将无法工作。

希望我错了,有人可以澄清我所缺少的吗?这可以解决吗,因为我在生产中有一个没有实施版本的 DTO?

4

1 回答 1

3

是的,当您第一次添加信息时这可能会很棘手,Version因为您希望在构造函数中拥有版本号,因此每次调用都被分配其隐式版本,同时每当您反序列化到新的 DTO 时都会使用相同的构造函数。

不幸的是,由于原始 DTO 中没有版本,因此它没有序列化到线路上,因此它永远不会覆盖隐式分配的版本字段。

为了解决这个问题(并在构造函数中保留隐式分配的版本号),您需要有效地重置反序列化中使用的版本。

您可以通过覆盖JsConfig.ModelFactoryon App_Start(即在您的 AppConfig 中)使用 JSON/JSV 序列化程序来执行此操作,这允许您控制为反序列化中使用的每个 POCO 类型创建的实例。

在这种情况下,我们希望将任何具有版本的 DTO 重置为0没有版本号的 DTO 被分配的方式,而具有版本号的0DTO 将覆盖它:

 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
于 2012-11-03T00:13:25.520 回答