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

DataContractSerializer.ReadObject() fails to create object when used with SvcUtils.exe

我运行SvcUtil.exe针对XSD文件生成class。然后尝试使用以下行从 XML 创建对象。我收到如下所示的错误。详细代码见下方

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.exe 在同一个 XSD 文件上。然后我可以使用 XmlSerializer.Deserialize().

将 XML 转换为对象

XSD 没有任何属性。我已经根据 XSD.

验证了 XML

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

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

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

svcutil.exe 为该类型生成数据契约 类 时,它将 类型名称 放入数据契约而不是 根元素名称。这似乎是有意的,请参阅 Svcutil generates wrong Name property value in DataContractAttribute. Perhaps it does this since the contract type itself could be re-used anywhere in the object graph, and there's no data contract equivalent of 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.