2016-08-03 10 views
1

xmlserialization을 사용하여 wcf 서비스가 있습니다. 다음과 같이 SoapUI에 보이는 몇 가지 클래스가있다 :IXmlSerializable 구현 후 WCF 서비스 xsd가 올바르지 않음

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

나는 그것에 IXmlSerializable 인터페이스를 구현했다가.

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

이는 GetSchema 방법의 다음 구현의 결과 일 수있다 : 그 일을 한 후, 클래스는 SoapUI 이상한 구조를 가지고있다?

<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를 반환해야합니다 : 아래

public XmlSchema GetSchema() 
    { 
     return null; 
    } 

서비스 WSDL에서 MyClass에 대한 섹션입니다. Proper way to implement IXmlSerializable?을 참조하십시오.

대신 클래스에 [XmlSchemaProvider(string methodName)]을 추가하고 형식 스키마를 지정하는 XmlQualifiedName (또는 익명 형식의 경우 XmlSchemaType)을 구현하는 정적 메서드를 구현해야합니다.

는 예를 들어, 원래의 유형은 아래와 같다 경우 : 내가 예상 스키마와 같은 임베디드 한 다음

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

: 같은

[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 재 구현이 보일 것이다 해당 유형 내부의 문자열 리터럴. 또는 디스크에서로드하거나 리플렉션으로 빌드 할 수도 있습니다.