如何使用 svcutil 从使用限制来隐藏元素的 Web 服务生成 C# WCF 代理?

问题描述 投票:0回答:1

我正在创建一个或多或少不受我控制的 Web 服务客户端。这是该架构的简化示例:

<xs:complexType name="A">
    <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="1" name="element1" type="xs:string" />
        <xs:element minOccurs="0" maxOccurs="1" name="element2" type="xs:string" />
    </xs:sequence>
</xs:complexType>

<xs:complexType name="B">
    <xs:complexContent>
        <xs:restriction base="A">
            <xs:sequence>
                <xs:element minOccurs="1" maxOccurs="1" name="element2" type="xs:string" />
            </xs:sequence>
        </xs:restriction>
    </xs:complexContent>
</xs:complexType>

简而言之,我们有一个包含所有元素的对象 A。该服务有多种基于 A 的类型,但有限制,因此继承的类型通常小于基本类型 - 此处以类型 B 为例。

在架构查看器(例如 Visual Studio 2010、SoapUI 等中的查看器)中,这看起来符合预期。 A 有 2 个元素,B 只有 1 个(= 元素 2)。

通过使用 svcutil,我获得了类型 A 和 B 中的完整元素集,或者在使用选项时,我收到错误消息,例如:

错误:无法导入命名空间“http://tempuri.org/XMLSchema.xsd”中的类型“B”。通过限制派生的复杂类型 不支持。更改架构以便类型可以映射到数据协定类型,或者使用 ImportXmlType 或使用 不同的序列化器。

在继承类型中隐藏字段/属性并不是我喜欢的做法/道路,但如果我无法让提供者更改 WSDL,似乎我必须这样做。

是否有 svcutil 的替代方案可以正确处理此问题,或者我是否必须手动编码我的代理?


更新1

正如 John Saunders 所指出的,我没有显示 svcutil 建议的结果。这部分是为了保持帖子简短......但这里是:

svcutil schema.xsd /importXmlTypes /datacontractonly 结果:

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="A", Namespace="http://tempuri.org/XMLSchema.xsd")]
public partial class A : object, System.Runtime.Serialization.IExtensibleDataObject
{

    private System.Runtime.Serialization.ExtensionDataObject extensionDataField;

    private string element1Field;

    private string element2Field;

    public System.Runtime.Serialization.ExtensionDataObject ExtensionData
    {
        get
        {
            return this.extensionDataField;
        }
        set
        {
            this.extensionDataField = value;
        }
    }

    [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]
    public string element1
    {
        get
        {
            return this.element1Field;
        }
        set
        {
            this.element1Field = value;
        }
    }

    [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]
    public string element2
    {
        get
        {
            return this.element2Field;
        }
        set
        {
            this.element2Field = value;
        }
    }
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Xml.Serialization.XmlSchemaProviderAttribute("ExportSchema")]
[System.Xml.Serialization.XmlRootAttribute(IsNullable=false)]

public partial class B : object, System.Xml.Serialization.IXmlSerializable
{

    private System.Xml.XmlNode[] nodesField;

    private static System.Xml.XmlQualifiedName typeName = new System.Xml.XmlQualifiedName("B", "http://tempuri.org/XMLSchema.xsd");

    public System.Xml.XmlNode[] Nodes
    {
        get
        {
            return this.nodesField;
        }
        set
        {
            this.nodesField = value;
        }
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        this.nodesField = System.Runtime.Serialization.XmlSerializableServices.ReadNodes(reader);
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        System.Runtime.Serialization.XmlSerializableServices.WriteNodes(writer, this.Nodes);
    }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public static System.Xml.XmlQualifiedName ExportSchema(System.Xml.Schema.XmlSchemaSet schemas)
    {
        System.Runtime.Serialization.XmlSerializableServices.AddDefaultSchema(schemas, typeName);
        return typeName;
    }
}

在 Xml 级别上工作是不可取的,并且会迫使我们编写包装器。从一开始就手动编写代理代码会更容易。

svcutil schema.xsd /serializer:XmlSerializer /datacontractonly 给出以下错误,这就是我要求替代工具的原因。

svcutil schema.xsd /serializer:XmlSerializer /datacontractonly 错误:无法在命名空间“http://tempuri.org/XMLSchema.xsd”中键入“B” 被进口。不支持通过限制派生的复杂类型。 更改架构以便类型可以映射到数据契约 类型或使用 ImportXmlType 或使用不同的序列化程序。

如果您使用 /dataContractOnly 选项导入数据合约 类型并收到此错误消息,请考虑使用 xsd.exe 反而。 xsd.exe 生成的类型可以在 Windows 中使用 申请后的沟通基础 服务合同上的 XmlSerializerFormatAttribute 属性。 或者,考虑使用 /importXmlTypes 选项进行导入 这些类型作为 XML 类型与 DataContractFormatAttribute 一起使用 您的服务合同上的属性。

使用 xsd schema.xsd /c 给出继承 A 的类型 B,而不隐藏 element1:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/XMLSchema.xsd")]
[System.Xml.Serialization.XmlRootAttribute("request", Namespace="http://tempuri.org/XMLSchema.xsd", IsNullable=false)]
public partial class B : A {
}

/// <remarks/>
[System.Xml.Serialization.XmlIncludeAttribute(typeof(B))]
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/XMLSchema.xsd")]
public partial class A {

    private string element1Field;

    private string element2Field;

    /// <remarks/>
    public string element1 {
        get {
            return this.element1Field;
        }
        set {
            this.element1Field = value;
        }
    }

    /// <remarks/>
    public string element2 {
        get {
            return this.element2Field;
        }
        set {
            this.element2Field = value;
        }
    }
}
.net web-services wsdl schema svcutil.exe
1个回答
0
投票

错误消息告诉您要么使用

/importXmlTypes
开关,要么更改为使用 XmlSerializer。来自帮助:

/importXmlTypes - 配置数据协定 用于导入非数据协定类型的序列化程序 作为 IXmlSerialized 类型。

/serializer:XmlSerializer - 生成使用 XmlSerializer 用于序列化和 反序列化

© www.soinside.com 2019 - 2024. All rights reserved.