获取ServiceStack以保留类型信息

lar*_*ars 20 .net c# serialization json servicestack

我正在使用ServiceStack将一些对象序列化和反序列化为JSON.考虑这个例子:

public class Container
{
    public Animal Animal { get; set; }
}

public class Animal
{
}

public class Dog : Animal
{
    public void Speak() { Console.WriteLine("Woof!"); }
}

var container = new Container { Animal = new Dog() };
var json = JsonSerializer.SerializeToString(container);
var container2 = JsonSerializer.DeserializeFromString<Container>(json);

((Dog)container.Animal).Speak(); //Works
((Dog)container2.Animal).Speak(); //InvalidCastException
Run Code Online (Sandbox Code Playgroud)

最后一行抛出InvalidCastException,因为Animal字段被实例化为Animal类型,而不是Dog类型.有什么办法可以告诉ServiceStack保留这个特定实例属于Dog类型的信息吗?

myt*_*thz 36

DTO中的继承是一个坏主意 - DTO应该尽可能地自我描述,并且通过使用继承客户端实际上不知道服务最终返回什么.这就是为什么你的DTO类在大多数"基于标准的"序列化器中无法正确/序列化的原因.

没有充分的理由在DTO中使用接口(并且很少有理由将它们放在POCO模型上),这是一种使用接口来减少应用程序代码中的耦合的商业习惯,这些代码被无意中泄露到DTO中.但是跨进程边界,接口只增加了耦合(它只在代码中减少),因为消费者不知道要反序列化的具体类型,所以它必须发出序列化特定的实现提示,现在将C#问题嵌入到线路上(所以现在甚至C#命名空间将破坏序列化)现在约束您的响应将被特定的序列化程序使用.在线路上泄漏C#问题违反了实现互操作性的服务的核心目标之一.

由于JSON规范中没有"类型信息"的概念,为了继承在JSON Serializers中工作,他们需要发出JSON 线格式的专有扩展以包含此类型信息 - 现在将您的JSON有效负载耦合到特定的JSON序列化器实现.

ServiceStack的JsonSerializer将此类型信息存储在__type属性中,并且由于它可以显着增加有效负载,因此只会为需要它的类型(即Interfaces后期绑定object类型或abstract类)发出此类型信息.

随着中说的解决办法是改变Animal要么是接口或抽象类,推荐但不DTO的使用继承.

  • 呃......回答我自己现在看似明显的评论/问题:消息不应该"成为"业务域对象,它应该"包含"一个(或更多).一个简单的问题是"有"与"是".因此,对于我的示例,UpdateUserMsg和RegisterUserMsg都包含UserAccount DTO.也不是UserAccount DTO.不需要继承. (4认同)