我在理解WCF中的ServiceKnownType时遇到了一些麻烦。
取自this blog,以下代码不起作用:
[DataContract(Namespace = “http://mycompany.com/”)]
public class Shape{…}
[DataContract(Namespace = “http://mycompany.com/”)]
public class Circle : Shape {…}
[ServiceContract]
public interface IMyServer
{
[OperationContract]
bool AddShape(Shape shape);
}
IMyServer client = new ChannelFactory<IMyServer>(binding, endPoint).CreateChannel();
client.AddShape(new Circle());
它不起作用的原因是因为您尝试添加一个圆,但servicecontract只允许一个Shape。你应该用知识型做一些事情,但我对它是如何工作有点困惑。
由于该代码在服务中,为什么不自动知道Circle是从Shape派生的?另外,ServiceKnownType实际上做了什么?
当ServiceKnownType放在DataContract下面时,显然可以使它工作。我猜它说,嘿,这种称为Shape的特殊对象类型也可以是一个圆圈。我无法理解为什么会这样做,因为如果你添加一个像Square这样的新类型,你将不得不为Shape类添加一个ServiceKnownType。如果它不能推断它,将KnownType放到Square而不是Shape上,它会不会有意义?所以Square说嘿,我是一个Shape,而你不必摆弄Shape类?如果您的Shape类内置在库中,并且您想要创建自己的衍生形状(如DiamondShape),则无法将其添加到Shape类,因为您无权访问源代码。
答案 0 :(得分:12)
问题是WCF没有进入所有程序集并试图找到所有可能的Shape子类型。它也不会使用XML文档传输类型信息(程序集,完全限定类型名称)。
因此,虽然在传出XML上生成标记“Circle”不是问题,但是传入的反序列化器不知道如何处理它。
KnownType“hack”就像已知类型的注册表,必须由双方实现。这是明确的。使用此注册表,反序列化器知道“Circle”反序列化为X类型,没有任何不公正的可能性,也无需解析派生类型的所有可用或可访问的程序集。
请记住,Square并没有说“我是一个形状”,它是一个XML标签,因此您不会轻易自动地知道要使用哪个.NET类。