【问题标题】:WCF service xsd after IXmlSerializable implementation is not correctIXmlSerializable 实现后的 WCF 服务 xsd 不正确
【发布时间】:2023-03-11 20:05:01
【问题描述】:

我有一个 wcf 服务(使用 xmlserialization)。 SoapUI 中有一些类看起来像这样:

     <MyClass>
        <propertyA>?</propertyA>
        <propertyB>?</propertyB>
     </MyClass>

我必须在它上面实现 IXmlSerializable 接口。 完成后,SoapUI 中的类有奇怪的结构:

     <MyClass>
        <xs:schema>
           <!--Ignoring type [{http://www.w3.org/2001/XMLSchema}schema]-->
        </xs:schema>
        <!--You may enter ANY elements at this point-->
     </MyClass>

这可能是 GetSchema 方法的以下实现的结果吗?

    public XmlSchema GetSchema()
    {
        return null;
    }

以下是来自服务 wsdl 的关于 MyClass 的部分:

<xs:element name="MyClass" form="unqualified" maxOccurs="1" minOccurs="0">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="xs:schema"/>
      <xs:any/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

【问题讨论】:

    标签: c# wcf serialization xsd ixmlserializable


    【解决方案1】:

    GetSchema() 应该总是返回 null。见Proper way to implement IXmlSerializable?

    相反,您需要将[XmlSchemaProvider(string methodName)] 添加到您的类中并实现一个静态方法,该方法返回一个XML 架构和一个指定该类型架构的XmlQualifiedName(或匿名类型的XmlSchemaType)。

    例如,如果您的原始类型如下所示:

    [DataContract(Namespace = "http://schemas.datacontract.org/2004/07/Question38741035")]
    [XmlRoot(Namespace = "http://schemas.datacontract.org/2004/07/Question38741035")]
    public class MyClass
    {
        [DataMember]
        public string PropertyA { get; set; }
    
        [DataMember]
        public decimal PropertyB { get; set; }
    }
    

    那么您的 IXmlSerializable 类型的重新实现应该类似于:

    [XmlSchemaProvider("GetSchemaMethod")]
    [XmlRoot(Namespace = "http://schemas.datacontract.org/2004/07/Question38741035")]
    public class MyClass : IXmlSerializable
    {
        public string PropertyA { get; set; }
    
        public decimal PropertyB { get; set; }
    
        const string XmlNamespace = "http://schemas.datacontract.org/2004/07/Question38741035";
    
        // This is the method named by the XmlSchemaProviderAttribute applied to the type.
        public static XmlQualifiedName GetSchemaMethod(XmlSchemaSet xs)
        {
            string schema = @"<?xml version=""1.0"" encoding=""utf-16""?>
    <xs:schema 
        xmlns:tns=""http://schemas.datacontract.org/2004/07/Question38741035"" 
        elementFormDefault=""qualified"" 
        targetNamespace=""http://schemas.datacontract.org/2004/07/Question38741035"" 
        xmlns:xs=""http://www.w3.org/2001/XMLSchema"">
      <xs:complexType name=""MyClass"">
        <xs:sequence>
          <xs:element minOccurs=""0"" name=""PropertyA"" nillable=""true"" type=""xs:string"" />
          <xs:element minOccurs=""0"" name=""PropertyB"" type=""xs:decimal"" />
        </xs:sequence>
      </xs:complexType>
      <xs:element name=""MyClass"" nillable=""true"" type=""tns:MyClass"" />
    </xs:schema>";
    
            using (var textReader = new StringReader(schema))
            using (var schemaSetReader = System.Xml.XmlReader.Create(textReader))
            {
                xs.Add(XmlNamespace, schemaSetReader);
            }
            return new XmlQualifiedName("MyClass", XmlNamespace);
        }
    
        #region IXmlSerializable Members
    
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }
    
        public void ReadXml(System.Xml.XmlReader reader)
        {
            if (reader.IsEmptyElement)
            {
                reader.Read();
                return;
            }
    
            var node = (XElement)XNode.ReadFrom(reader);
            if (node != null)
            {
                var ns = (XNamespace)XmlNamespace;
    
                PropertyA = (string)node.Element(ns + "PropertyA");
                PropertyB = (decimal)node.Element(ns + "PropertyB");
            }
        }
    
        public void WriteXml(System.Xml.XmlWriter writer)
        {
            if (PropertyA != null)
                writer.WriteElementString("PropertyA", XmlNamespace, PropertyA);
            writer.WriteStartElement("PropertyB", XmlNamespace);
            writer.WriteValue(PropertyB);
            writer.WriteEndElement();
        }
    
        #endregion
    }
    

    在这里,我将预期的模式作为字符串文字嵌入到类型中。或者,您可以从磁盘加载它或通过反射构建它。

    【讨论】:

      猜你喜欢
      • 2010-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-30
      • 1970-01-01
      • 1970-01-01
      • 2011-08-04
      相关资源
      最近更新 更多