引用通用类型的 XSD Gen 类

Posted

技术标签:

【中文标题】引用通用类型的 XSD Gen 类【英文标题】:XSD Gen Classes That Reference a Common Type 【发布时间】:2012-01-09 20:01:39 【问题描述】:

我正在使用 XSD 在 C# 中定义我的 DTO 类型。我正在使用 XSD.exe 从 XSD 生成类。

我有一个定义地址类型的 Common.xsd,我想在多个类中使用它:

  <xs:complexType name="Address">
    <xs:sequence>
      <xs:element name="Street1" type="xs:string"/>
      <xs:element name="Street2" type="xs:string"/>
      <xs:element name="City" type="xs:string"/>
      <xs:element name="State" type="xs:string"/>
      <xs:element name="Zip" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

  <xs:element name="Address" type="mhm:Address"/>

我在公司 XSD 中引用了这个:

  <xs:include schemaLocation=".\Common.xsd"/>
  <xs:complexType name="Company">
    <xs:sequence>
      <xs:element name="AdmCode" type="xs:string"/>
      <xs:element name="CompanyCode" type="xs:string"/>
      <xs:element name="Name" type="xs:string"/>
      <xs:element ref="mhm:Address"/>
    </xs:sequence>
  </xs:complexType>

  <xs:element name="Company" type="mhm:Company"/>

还有一个员工 XSD:

  <xs:include schemaLocation=".\Common.xsd"/>
  <xs:complexType name="Employee">
    <xs:sequence>
      <xs:element name="EmployeeNumber" type="xs:int"/>
      <xs:element name="FirstName" type="xs:string"/>
      <xs:element name="LastName" type="xs:string"/>
      <xs:element name="Address" type="mhm:Address"/>
    </xs:sequence>
  </xs:complexType>
  <xs:element name="Employee" type="mhm:Employee"/>

我使用这个命令行生成类:

xsd .\XSD\Common.xsd /c /o:. /n:"DomainModel"
xsd .\XSD\Employee.xsd /c /o:. /n:"DomainModel"
xsd .\XSD\Company.xsd /c /o:. /n:"DomainModel"

我去编译项目的时候发现在Company.cs类文件和Employee.cs类文件中都生成了Address类型。

如何在 Common.cs 类文件中获取只生成一次的 Address 类型,而 Employee 和 Company 类型使用这个单一的 Address 类型?

【问题讨论】:

【参考方案1】:

您可以将XSD.exe 与多个文件参数一起使用:

xsd .\XSD\Common.xsd .\XSD\Employee.xsd .\XSD\Company.xsd /c /o:. /n:"DomainModel"

【讨论】:

谢谢马特 - 如果我尝试 xsd.exe 无法验证架构验证警告:全局元素“mhmr.com/domain/v1_0:A 地址”已被声明。第 20 行,位置 4。架构验证警告:complexType 'mhmr.com/domain/v1_0:Address' 已被声明。第 10 行,位置 4。架构验证警告:全局元素“mhmr.com/domain/v1_0:A 地址”已被声明。第 20 行,位置 4。 您可以尝试从命令行中排除“common.xsd”吗?我认为由于它是通过 XSD 包含的,您可能不需要在命令行中传递它。 实际上,您的第一个答案是正确的。所有的类都被生成到命令行中的最后一个 xsd 类中。我看代码的距离不够近,并且在尝试重新编译之前没有删除其他类文件。加分(!)您知道如何将每种 C# 类型生成到其自己的类文件中吗? ***.com/questions/8315129/… @RobertMS 回答您关于拆分文件的问题,请参阅我的回答。【参考方案2】:

您基本上希望将常用类型拆分为一个公共程序集,该程序集由您的其他类型引用。你有两个选择:

    手动拆分它们。我知道这是一个生成的文件,但如果你的源模式是相当静态的,那么这是一个一次性的练习。 请改用 svcutil.exe。然而,这要复杂得多,实际上你甚至可能无法做到这一点,除非你的模式都遵守某些准则。如果您有兴趣,请参阅下面的流程。

如果您喜欢上面的选项 2,那么这里是一般过程:

    使用 svcutil 上的 /dconly 标志从 Common.xsd 中提取类型。这将生成一个包含常用类型的类文件。 将此类编译成程序集 使用 /r 标志从 A.xsd 中提取类型并引用您的 CommonTypes.dll 程序集。 对 B.xsd 执行相同操作

但是,此方法基于 svcutil 使用 DataContractSerializer 来完成工作,因为 /r 标志对 XmlSerializer 不可用。这只有在您的模式遵守相当严格的 DCS 规则时才有效(可以在此处找到:http://msdn.microsoft.com/en-us/library/ms733112.aspx)。

如果不遵守这些规则,那么 svcutil 将回退到使用不支持 /r 标志的 XmlSerializer。

【讨论】:

谢谢休。将所有生成的类放在一个代码文件中并不是什么大问题,因为它们是生成的,因此我不会直接接触它们,但会编辑 xsd。我实际上会将代码生成作为构建步骤。

以上是关于引用通用类型的 XSD Gen 类的主要内容,如果未能解决你的问题,请参考以下文章

关于包含文件和代码生成的 XSD.exe 问题

Java基础--关于Object的一些通用方法

自动装箱拆箱

Swift如何实现通用类型的弱引用数组(上)

Swift如何实现通用类型的弱引用数组(下)

2017-04-17类库通用变量is和as委托