当引用抽象类时,C#WCF服务引用公开具体类而不是继承的抽象类

时间:2012-07-19 16:43:46

标签: c# web-services wsdl abstract-class service-reference

我正在使用wsdl中的Visual Studio 2010生成C#服务引用。 (简化示例,请原谅任何语法错误):

<xs:complexType name="Constraints">
  <xs:sequence>
    <xs:element minOccurs="1" maxOccurs="unbounded" ref="p:Constraint" />
  </xs:sequence>
</xs:complexType>

<xs:element name="Constraint" type="p:ConstraintType" />

<xs:complexType abstract="true" name="ConstraintType />

<xs:complexType name="RelConstraint" >
  <xs:complexContent>
    <xs:extension base="p:ConstraintType">
     ...
    </xs:extension>
  <xs:complexContent>
</xs:complexType>

<xs:complexType name="Logic" abstract="true">
  <xs:complexContent>
    <xs:extension base="p:ConstraintType">
     ...
    </xs:extension>
  <xs:complexContent>
</xs:complexType>  

<xs:complexType name="AndLogic" >
  <xs:complexContent>
    <xs:extension base="p:Logic">
     ...
    </xs:extension>
  <xs:complexContent>
</xs:complexType>

Constraints的元素是.Item not .Constraint(很好,我知道这是抽象的。)

但是,Constraints.Item类型是RelConstraint而不是ConstraintType,因此它不会将AndLogic识别为可能的类型。

所以看起来如果一个具体类型被抽象为一个层次而另一个被抽象为两个层次,那么服务引用设置对类的任何引用只抽象一个层次。

(例如 ConcreteClassA扩展了AbstractClassC, ConcreteClassB扩展了AbstractClassB,它扩展了AbstractClassC,

ConcreteClassX具有元素AbstractClassC,它应该是该类型。 但是,该元素的类型为ConcreteClassA)

有解决方法吗?

这与WHY doesn't WCF 'properly' consume/expose abstract types when hosted as a web service

有关

1 个答案:

答案 0 :(得分:0)

所以我的第一个想法就是从元素声明中删除abstract =“true”,但是将它留在了类型声明上。这是在删除任何内容之前声明元素和类型:

<xs:element abstract="true" name="Logic" substitutionGroup="p:Constraint" type="p:LogicType" />

<xs:complexType name="LogicType" abstract="true">
  <xs:complexContent>
    <xs:extension base="p:ConstraintType">
      ...
    </xs:extension>
  <xs:complexContent>
</xs:complexType>

Visual Studio实际上正确生成了代码! 从我能找到的,从元素中删除抽象而不是类型不是抽象对象的错误实现。 (但是,我仍然对这一点感到厌倦)。

所以我写了一些测试xml并将它从我的服务器发送到我的c#程序。当然......它不会正确地序列化对象(它们都被设置为null)。

所以我最后直接查看了Reference.cs文件,看看我是否能解决问题。

[System.Xml.Serialization.XmlElementAttribute("Logic", typeof(LogicType), Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("RelConstraint", typeof(RelConstraintType), Order = 0)]
public ConstraintComponentType Item

看起来没错,但我决定为AndLogic和我的其他逻辑类型添加XmlElementAttribute声明以查看发生了什么。它最终正确地序列化了测试数据!

[System.Xml.Serialization.XmlElementAttribute("And", typeof(AndType), Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("Logic", typeof(LogicType), Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("RelConstraint", typeof(RelConstraintType), Order = 0)]
public ConstraintComponentType Item

所以我最终做的是将abstract =“true”放回我的元素上以使我的模式正确,然后进入并执行上述步骤,同时更改错误生成类型的任何地方,例如。

[System.Xml.Serialization.XmlElementAttribute("Logic", typeof(LogicType), Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("RelConstraint", typeof(RelConstraintType), Order = 0)]
public RelConstraintType Item

所以唯一的问题是,如果你想重新生成服务引用,你必须返回并再次手动编辑Reference.cs文件。