2016-08-03 14 views
1

Ich habe einen Dienst wcf (mit Xmlserialization). Es gibt einige Klassen, die wie folgt in SoapUI aussieht:WCF-Dienst xsd nach IXmlSerializable-Implementierung ist nicht korrekt

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

I IXmlSerializable Schnittstelle auf sie umsetzen musste. Nachdem es zu tun, Klasse hat seltsame Struktur in SoapUI:

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

es ein Ergebnis der folgenden Umsetzung der GetSchema-Methode sein kann?

public XmlSchema GetSchema() 
    { 
     return null; 
    } 

Im Folgenden finden Sie Abschnitt über MyClass aus dem Dienst 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> 

Antwort

1

GetSchema() sollte immer null zurück. Siehe Proper way to implement IXmlSerializable?.

Stattdessen müssen Sie [XmlSchemaProvider(string methodName)] Ihre Klasse hinzuzufügen und eine statische Methode zu implementieren, die ein XML-Schema und ein XmlQualifiedName (oder XmlSchemaType für anonyme Typen) gibt, die das Schema des Typs angibt.

Zum Beispiel, wenn Ihre ursprüngliche Art wie folgt aussieht:

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

Dann Ihre IXmlSerializable Neuimplementierung des Typs etwas aussehen soll:

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

Here I eingebettet habe das erwartete Schema als ein Zeichenfolgenliteral innerhalb des Typs. Alternativ könnten Sie es von der Festplatte laden oder durch Reflektion aufbauen.