1

我正在使用来自 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 而不是 .Constraint (这很好,我知道这发生在抽象中)。

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

因此,如果一种具体类型被抽象一层,另一种被抽象两层,那么服务引用设置对只抽象一层的类的任何引用。

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

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

有解决办法吗?

这与为什么 WCF 在作为 Web 服务托管时不能“正确”使用/公开抽象类型有关

4

1 回答 1

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# 程序。当然......它不会正确序列化对象(它们都设置为空)。

所以最后还是直接看了一下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 文件。

于 2012-07-26T13:35:34.690 回答