不久前,我们需要在课堂上创建一个 C# Web 客户端作为项目的一部分。老师指示我们将属性放在DataContract
将要通过的每个班级之上。
然后老师告诉我们,如果你有这样的事情:
一种 / \ / \ 公元前
您需要按以下方式编写A类:
[DataContract]
[KnownType(typeof(B))]
[KnownType(typeof(C))]
public class A
{
}
这不是完全违背了多态性的想法吗?为什么一个类应该知道谁继承了这个类?
不久前,我们需要在课堂上创建一个 C# Web 客户端作为项目的一部分。老师指示我们将属性放在DataContract
将要通过的每个班级之上。
然后老师告诉我们,如果你有这样的事情:
一种 / \ / \ 公元前
您需要按以下方式编写A类:
[DataContract]
[KnownType(typeof(B))]
[KnownType(typeof(C))]
public class A
{
}
这不是完全违背了多态性的想法吗?为什么一个类应该知道谁继承了这个类?
这与 C# 和多态性没有任何关系。而不是序列化。WCF 基础结构需要能够从网络中取出字节数组之类的东西并从中创建一个对象。如果类A
是一种abstract
类型,则无法实例化该对象。框架需要知道它可能通过线路接收什么类型,以便它可以检查元数据并实例化正确类型的对象。
换句话说,属性不会告诉类有关它的继承者的任何信息(实际上,列表不需要包括所有继承者);这是严格的,所以框架将知道它可以期望被要求构造什么类型。
不过,我要补充一点,并不总是需要添加DataContract
and属性。DataMember
它们可用于您可能希望进行更细粒度控制的场景,例如从序列化中排除公共属性。通常,如果类型是可序列化的,则可以在没有属性的情况下传递它。
WCF 序列化程序将继承的概念与多态性的概念分开。CLR 继承仅意味着就序列化程序而言,基类成员自动添加到派生类中,并不意味着 XML 文档中的两个元素之间存在任何类型的关系。要获得多态性,您必须明确告诉序列化程序派生类的 XML 表示可以替代基类的 XML 表示。
我个人觉得区分很方便。我有时使用 CLR 继承而不KnownType
向类添加公共属性,而不暗示它们之间存在任何类型的业务关系。
首先,正如 Daniel 所说,您说的是 Windows 通信基金会 (WCF),而不是 web。
通过装饰类,您是在告诉客户他必须知道两个类才能使用类“A”,例如
[DataContract]
[KnownType(typeof(B))]
[KnownType(typeof(C))]
public class A
{
[DataMember]
private SuperClass myProp;
}
public Class B : SuperClass {}
public Class C : SuperClass {}
请查看此链接以获取更多信息:MSDN DataContract