与SvcUtils.exe一起使用时,DataContractSerializer.ReadObject()无法创建对象

时间:2015-12-06 23:54:05

标签: xsd deserialization xmlserializer datacontractserializer xsd2code

我针对XSD文件运行了SvcUtil.exe来生成类。然后尝试使用以下行从XML中创建Object。我收到如下错误。请参阅下面的详细代码。

PersonType prs = (PersonType)xs.ReadObject(new MemoryStream(File.ReadAllBytes(sFileName)));

Error in line 3 position 58. Expecting element 'PersonType' from namespace 'http://service.a1.com/base1/2005/'.. Encountered 'Element'  with name 'Person', namespace 'http://service.a1.com/base1/2005/'. 

使用的命令

svcutil.exe" "C:\Temp\S1\UseXSDExe\UseXSDExe\Sample2\Prs.xsd" /t:code /language:cs /out:C:\SPrxy.cs /dconly

完整代码

(class generated by SvcUtils.exe)
    [assembly: System.Runtime.Serialization.ContractNamespaceAttribute("http://service.a1.com/base1/2005/", ClrNamespace="service.a1.com.base1._2005")]
    namespace service.a1.com.base1._2005
    {
        using System.Runtime.Serialization;


        [System.Diagnostics.DebuggerStepThroughAttribute()]
        [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
        [System.Runtime.Serialization.DataContractAttribute(Name="PersonType", Namespace="http://service.a1.com/base1/2005/")]
        public partial class PersonType : object, System.Runtime.Serialization.IExtensibleDataObject
        {
            private System.Runtime.Serialization.ExtensionDataObject extensionDataField;

            private string LastNameField;

            private string FirstNameField;

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

            [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true, EmitDefaultValue=false)]
            public string LastName
            {
                get
                {
                    return this.LastNameField;
                }
                set
                {
                    this.LastNameField = value;
                }
            }

            [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=1)]
            public string FirstName
            {
                get
                {
                    return this.FirstNameField;
                }
                set
                {
                    this.FirstNameField = value;
                }
            }
        }
    }

(code used for converting XML to object)
    public static void convertToObject(string sFileName)
    {
        DataContractSerializer xs = new DataContractSerializer(typeof(PersonType));
        PersonType Person = (PersonType)xs.ReadObject(new MemoryStream(File.ReadAllBytes(sFileName)));

    }

(XSD)

    <?xml version="1.0" encoding="utf-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://service.a1.com/base1/2005/"  xmlns:bse1="http://service.a1.com/base1/2005/" elementFormDefault="qualified">
        <xs:complexType  name="PersonType">
            <xs:sequence>
                <xs:element minOccurs="1" maxOccurs="1" name="LastName" type="xs:string" />
                <xs:element minOccurs="0" maxOccurs="1" name="FirstName" type="xs:string" />
            </xs:sequence>
        </xs:complexType>
        <xs:element name="Person" type="bse1:PersonType"/> 
    </xs:schema>

(XML)

    <?xml version="1.0" encoding="utf-8"?>
    <pr:Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                xsi:schemaLocation="http://service.a1.com/base1/2005/ Prs.xsd" 
                xmlns:pr="http://service.a1.com/base1/2005/"> 
        <pr:LastName>   Lane </pr:LastName>
        <pr:FirstName>  Fane </pr:FirstName>
    </pr:Person>

我在同一个XSD文件上运行了XSD.exe。然后我可以使用XmlSerializer.Deserialize()将XML转换为Object。

XSD没有任何属性。我已经针对XSD验证了XML。

请告诉我Deserialize()失败的原因。

1 个答案:

答案 0 :(得分:1)

您的XSD指定了不同的根元素名称和数据类型名称:

 <xs:element name="Person" type="bse1:PersonType"/> 

svcutil.exe为此类型生成数据协定类时,它会将类型名称放入数据协定而不是根元素名称。这似乎是有意的,请参阅Svcutil generates wrong Name property value in DataContractAttribute。也许这样做是因为契约类型本身可以在对象图中的任何地方重复使用,并且当有问题的类型是文档的时候,没有相当于XmlRoot的数据契约只应用 根元素。

作为一种解决方法,您有几个选择:

  1. constructing the serializer

    时对预期的根元素名称进行硬编码
        var xs = new DataContractSerializer(typeof(service.a1.com.base1._2005.PersonType), "Person", "http://service.a1.com/base1/2005/");
    
  2. 将XML预加载到XDocument并在构造序列化程序时使用实际的根元素名称:

        var doc = XDocument.Load(sFileName);
        service.a1.com.base1._2005.PersonType person;
        var xs = new DataContractSerializer(typeof(service.a1.com.base1._2005.PersonType), doc.Root.Name.LocalName, "http://service.a1.com/base1/2005/");
        using (var reader = doc.CreateReader())
        {
            person = (service.a1.com.base1._2005.PersonType)xs.ReadObject(reader);
        }
    
  3. 或使用XmlSerializer