【问题标题】:C# WCF Service Reference exposes concrete class instead of inherited abstract class when abstract class is referencedC# WCF 服务引用在引用抽象类时公开具体类而不是继承的抽象类
【发布时间】:2012-07-19 16:43:46
【问题描述】:

我正在使用我的 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 扩展 AbstractClassC,

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

有解决办法吗?

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

【问题讨论】:

  • 我做不到。我具体需要澄清什么或添加细节?
  • 如果我错了,请纠正我,你有 ConstraintType、继承 ConstraintType 的 RelConstratint、继承 ConstraintType 的 Logic 和继承 Logic 的 AndLogic。这是正确的吗?
  • 是的,没错。 Constraints 有一个 ConstraintType 列表,但生成的服务引用将该列表设置为 RelConstraint 列表
  • 这是什么服务? WCF、.asmx 还是其他?你是怎么吃的?作为 Web 服务参考还是作为服务参考 (WCF)?
  • 你能修改wsdl吗?如果是这样,请尝试从 ConstraintType 和 Logic 中删除 abstract="true"。

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


【解决方案1】:

所以我几乎可行的第一个想法是从元素声明中删除 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 文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-27
    • 2011-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多