为什么WCF在托管为Web服务时“正确”使用/公开抽象类型

时间:2009-05-08 13:01:59

标签: wcf

我已经设计了很长一段时间的网络服务,但直到最近才开始提供“复杂的”WCF服务。我对WCF中对抽象类型明显缺乏“适当支持”感到困惑。当然 - 你可以使用它们 - 确保你可以让它们“工作”......你最终不会得到你想要的东西......

第一个问题是,如果从具有抽象类型的wsdl生成代码,则会得到截然不同的代码,因为它会回退到xmlserializer而不是DataContractSerializer。这显然有点不太理想......我想使用花哨的新的更快的序列化器,请谢谢...(以及Service / DataContract附带的所有内容)

另一方面 - 如果您首先使用代码并将正确归因的抽象wcf类作为Web服务公开,则公开的wsdl不包含abstract =“true”属性,使“抽象类”在技术上具体......这当然不是我想要的......

我有一个解决方法,但它涉及一个疯狂的'hackery'我首先创建wsdl / xsd合同,删除任何abstract =“true”(哦 - 我不能提到我不能使用属性xsd应该我们)然后svcuitl结果...但是现在我离开了ac#api,它有一个CONCRETE抽象类,然后我需要修改它来添加抽象关键字...这个'有效'但是这是一个巨大的皮塔饼 - 而且不容易“编写脚本”...

这一切都被打破了!我希望有人可以向我解释'为什么'这是......我欢迎那些没有引用“可靠”资源的答案,但我真的在等待这个人告诉我 - 用适当的文件(比如来自好朋友Don Box本人)为什么这才是......因为我只是不明白......

非常感谢 - 如果有人想了解更多详情 - 请告诉我们!

更新样本请求的补充 - 从c#开始

[ServiceContract]
public interface IShapeTest
{
  [OperationContract]
  AbsShape EchoShape(AbsShape shape);
}

public class ShapeTestImpl : IShapeTest
{
  public AbsShape EchoShape(AbsShape shape)
  {
    return shape;
  }
}

[KnownType(typeof(Square))]
public abstract class AbsShape
{
  [DataMember]
  public int numSides;
}

public class Square : AbsShape
{
  public Square() : base()
  {
    numSides = 4;//set the numSides to 'prove' it works
  }
}

预期类型:

<xs:complexType name="AbsShape" abstract="true"> <!--NOTE abstract="true"-->
  <xs:sequence>
    <xs:element minOccurs="0" name="numSides" type="xs:int"/>
  </xs:sequence>
</xs:complexType>

ACTUAL EMITTED TYPE:

<xs:complexType name="AbsShape"> <!--NOTE the lack of abstract="true"-->
  <xs:sequence>
    <xs:element minOccurs="0" name="numSides" type="xs:int"/>
  </xs:sequence>
</xs:complexType>

5 个答案:

答案 0 :(得分:5)

好吧,因为WCF不传递对象,它传递消息。这不是远程处理,因此客户端上的类型与服务器上的类型不同 - 它只是各种属性的保持类。实现“abstract =”true“根本没有意义。消息只是数据 - 客户端如何知道要使用的具体类型,因为您不是在共享类,而只是表示消息。

答案 1 :(得分:2)

“abstract”是一个实现细节。它在服务合同中没有地位。当然,只要你坚持要求你的调用者必须知道你正在返回一个抽象类型,WCF就必须依赖于一个可以暴露这个事实的序列化器:你又回到了被XmlSerializer困住的地方。

我怀疑你正在使用抽象,因为这是做事的OO方式。但是你没有做OO,你正在做Web服务 - SOA。有区别。

答案 2 :(得分:1)

这个问题的前提是WCF应该将XSD complexType元素与设置为true的抽象属性映射为C#抽象类。如果查看WSDL spec on future extensibility,,您将看到一个示例,说明规范如何使用此XSD功能来添加“元素项”,而无需修改WSDL规范本身。

XSD抽象属性的目的是允许其他XSD“类型”继承基类型的定义。这可能听起来像@dovholuk正在寻找WCF,但实际上它是一个XSD类型定义的设备。此XSD功能与将XML序列化为C#类构造无关,因为它旨在使用 XSD定义中。总结@blowdart&amp; @JohnSaunders,WCF是消息交换的抽象,其中基于XSD的类型定义是一个实现细节。

答案 3 :(得分:1)

当您使用Java EE时,抽象类型上的属性“abstract = true”以及类型的继承将保留在WSDL中。在WSDL和XSD中保留对象模型中传统Java关键字(如“abstract”或“extends”)的任何使用。不需要特殊属性或修改。

WCF服务无法在WSDL中生成抽象属性。 WCF也无法遍历对象模型继承,需要使用KnownTypeAttribute才能使正确的XSD继承产生WSDL。

然而,WCF客户端将从一个服务生成WSDL的抽象类型,该服务将某些类型描述为抽象,并保留任何类型的继承(使用Visual Studio中的“服务引用”将客户端设置为Java EE服务例如)。

因此,WCF尊重客户端代理的WSDL中定义的抽象类型,但它不会在WSDL创建的服务中创建抽象类型(也许没有特别注意,比如继承所需的KnownTypeAttribute)。

答案 4 :(得分:0)

使用[XmlSerializerFormat]属性