数据契约序列化器要求超类了解子类
我遇到这个问题, “反序列化器不了解映射到此合约的任何类型” 谷歌搜索后,我到达了这篇文章
其中答案说,基类必须声明“KnownTypes”,例如 [DataContract, KnownType(typeof(Subclass)) ...],
如果我必须在我的父类中声明它,[DataContract, KnownType(typeof(Subclass))],这是否违反了父类的 OO 设计原则类不需要知道子类吗?
这样做的正确方法是什么?
I got this problem,
"The deserializer has no knowlege of any type that maps to this contract"
After googling, I reached this post
The deserializer has no knowlege of any type that maps to this contract
where the answer says, the base class have to declare "KnownTypes" like
[DataContract, KnownType(typeof(Subclass)) ...],
If I have to declare this in my parent class, [DataContract, KnownType(typeof(Subclass))], doesn't it break the principles of OO Design that parent class doesn't have to know about subclass?
What is the right way of doing this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
序列化器的设计方式是,如果它序列化一个对象,它应该能够读回它。如果您尝试序列化一个声明类型为“Base”但实际类型为“Derived”的对象(请参见下面的示例),如果您希望能够从序列化对象中读回“Derived”的实例,您需要以某种方式在 XML 中注释该实例不是其声明的类型。
该类型的序列化版本将类似于下面的 XML:
当反序列化该类型时,序列化程序将查看“actualType”(不是实际名称)属性,并且必须找到该类型、对其进行初始化,然后设置其属性。让序列化程序(在 Silverlight 中是一个受信任的程序集,并且比普通用户代码拥有更多的“权限”)创建任意类型是一个潜在的安全问题,因此这是限制可以反序列化的类型的原因之一。并且根据序列化器的设计(如果我们可以序列化它,我们应该能够反序列化它),序列化也会因此失败。
另一个问题是,序列化数据通常用于在不同的服务、不同的计算机中并且可能使用不同的语言之间进行通信。有可能(而且通常是这种情况)客户端的命名空间中有一个类,它与服务器端的类具有相似的数据契约,但它们具有不同的名称和/或驻留在不同的命名空间中。因此,简单地在“actualType”属性中添加 CLR 类型名称在这种情况下也不起作用([KnownType] 属性帮助序列化程序将数据协定名称/命名空间映射到实际的 CLR 类型)。另外,如果您正在与不同语言/平台(即 Java)中的服务进行通信,则 CLR 类型名称甚至没有意义。
另一个更详细的解释在帖子 http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx - 它谈论 [ServiceKnownType] 而不是 [KnownType] ],但原理是一样的。
最后,关于你的问题:它是否违反了 OO 原则?是的,这个原则被打破了,这是分布式(面向服务)应用程序中客户端和服务之间失去耦合所付出的代价。
The serializer is designed in a way that, if it serializes an object, it should be able to read it back. If you attempt to serialize an object with a declared type of 'Base', but an actual type of 'Derived' (see example below), if you want to be able to read back from the serialized object an instance of 'Derived', you need to somehow annotate the XML that the instance is not of the type of which it was declared.
The serialized version of the type would look something like the XML below:
When the type is being deserialized, the serializer will look at the "actualType" (not actual name) attribute, and it will have to find that type, initialize it, and set its properties. It's a potential security issue to let the serializer (with in Silverlight lives is a trusted assembly and has more "rights" than the normal user code) to create arbitrary type, so that's one reason for limiting the types which can be deserialized. And based on the design of the serializer (if we can serialize it, we should be able to deserialize it), the serialization fails for that reason as well.
Another problem with that is that the serialized data is often used to communicate between different services, in different computers, and possibly with different languages. It's possible (and often it is the case) that you have a class in a namespace in the client which has a similar data contract to a class in the server side, but they have different names and / or reside in different namespaces. So simply adding the CLR type name in the "actualType" attribute won't work in this scenario either (the [KnownType] attribute helps the serialzier map the data contract name / namespace to the actual CLR type). Also, if you're talking to a service in a different language / platform (i.e., Java), CLR type names don't even make sense.
Another more detailed explanation is given at the post http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx - it talks about [ServiceKnownType] instead of [KnownType], but the principles are the same.
Finally, about your question: does it break that OO principle? Yes, that principle is broken, that's a price to pay for being able to have lose coupling between the client and services in your distributed (service-oriented) application.
是的,它打破了面向对象设计的原则。这是因为 SOA 是关于共享契约(服务 ABC 中的 C)而不是类型,而 OO 是关于类型层次结构。这样想,服务的客户端可能不是使用 OO 语言,但仍然可以应用 SOA 原则。如何在服务器端完成映射是一个实现问题。
Yes it breaks the principles of OO design. This is because SOA is about sharing contracts (the C in ABC of services) and not types, whereas OO is about type hierarchies. Think like this the client for a service may not be even in an OO language but SOA principles can still be applied. How the mapping is done on server side is an implementation issue.