2016-08-03 3 views
1

У меня есть служба wcf (с использованием xmlserialization). Существует некоторый класс, который выглядит в SoapUI так:WCF-сервис xsd после IXmlSerializable реализация неверна

 <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; 
    } 

Ниже раздел о MyClass от службы WSDL:

<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> 

ответ

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 
} 

Здесь я внедренный ожидаемая схема, как строковый литерал внутри типа. В качестве альтернативы вы можете загрузить его с диска или создать его путем отражения.