我正在使用 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
最后一行抛出 InvalidCastException,因为 Animal 字段被实例化为 Animal 类型,而不是 Dog 类型。有什么方法可以告诉 ServiceStack 保留该特定实例属于 Dog 类型的信息吗?
DTO 中的继承是一个坏主意 - DTO 应该尽可能自描述,并且通过使用继承,客户端实际上不知道服务最终返回什么。这就是为什么您的 DTO 类在大多数“基于标准”的序列化器中无法正确反序列化的原因。
没有充分的理由在 DTO 中使用接口(并且很少有理由在 POCO 模型上使用它们),这是一种使用接口来减少应用程序代码中的耦合的货物崇拜习惯,而这些代码被不假思索地泄漏到了 DTO 中。但跨进程边界,接口只会增加耦合(只是在代码中减少),因为消费者不知道要反序列化成什么具体类型,因此它必须发出特定于序列化的实现提示,这些提示现在在线上嵌入了 C# 关注点(所以现在甚至C# 命名空间将破坏序列化),并且现在限制您的响应由特定序列化程序使用。在线泄露 C# 问题违反了服务实现互操作性的核心目标之一。
由于 JSON 规范中没有“类型信息”的概念,为了让继承在 JSON 序列化器中工作,它们需要发出专有扩展 to the JSON 线格式 http://www.json.org/包含此类型信息 - 现在将您的 JSON 负载耦合到特定的 JSON 序列化器实现。
ServiceStack 的 JsonSerializer https://github.com/ServiceStack/ServiceStack.Text/将此类型信息存储在__type属性,并且由于它会大大增加有效负载,因此只会为需要它的类型发出此类型信息,即Interfaces
, 后期绑定object
类型或abstract
类。
话虽如此,解决方案是改变Animal
要么成为界面 or an abstract类,但是建议不要在 DTO 中使用继承。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)