为什么在映射具有相同名称但不同名称空间的类的对象图时,XmlSerializer无法初始化?

时间:2022-11-20 15:07:25

I'm receiving XML from a third party that has no namespaces. The XML schema, in a simplified and obfuscated form, looks like the following:

我从没有名称空间的第三方接收XML。 XML模式以简化和混淆的形式显示如下:

<Root>
    <Address>
        <PostalCode>57373</PostalCode>
    </Address>
    <ReportAReport>
        <Address>
            <Zip>18573</Zip>
        </Address>
    </ReportAReport>
</Root>

Please take note that there are two distinct Address classes here. These are actually defined as two different complexTypes, each in a spearate XML schema which I have received from the third party. One schema reflects the Root model, while the other schema reflects the model for ReportAReport Each Address class has distinct properties.

请注意,这里有两个不同的地址类。这些实际上被定义为两个不同的complexTypes,每个都在我从第三方收到的spearate XML模式中。一个模式反映了Root模型,而另一个模式反映了ReportAReport的模型。每个Address类都有不同的属性。

I represent each in a namespace, treating each XML schema as its own namespace. In fact, the schemas have namespaces defined, but the XML response I receive from the third party has chosen to omit these namespaces for some reason.

我在命名空间中表示每个,将每个XML模式视为自己的命名空间。实际上,模式定义了名称空间,但是我从第三方收到的XML响应因某些原因选择省略这些名称空间。

Namespace: MyCompany.MyProject

namespace MyCompany.MyProject
{
    public class Root
    {
        public Address Address { get; set; }
        public ReportAReport ReportAReport { get; set; }
    }

    public class Address
    {
        public string PostalCode { get; set; }
    }
}

Namespace: MyCompany.MyProject.ReportA

namespace MyCompany.MyProject.ReportA
{
    public class ReportAReport
    {
        public Address Address { get; set; }
    }

    public class Address
    {
        public string Zip { get; set; }
    }
}

The exception I'm getting is as follows:

我得到的例外情况如下:

Result Message: Unable to create instance of class MyCompany.MyProject.Test.AggregatorTests. Error: System.TypeInitializationException: The type initializer for 'MyCompany.MyProject.Test.AggregatorTests' threw an exception. ---> System.InvalidOperationException: There was an error reflecting type 'MyCompany.MyProject.Root'. ---> System.InvalidOperationException: There was an error reflecting property 'ReportAReport'. ---> System.InvalidOperationException: There was an error reflecting type 'MyCompany.MyProject.ReportA.ReportAReport'. ---> System.InvalidOperationException: There was an error reflecting property 'Address'. ---> System.InvalidOperationException: There was an error reflecting type 'MyCompany.MyProject.ReportA.Address'. ---> System.InvalidOperationException: Types 'MyCompany.MyProject.ReportA.Address' and 'MyCompany.MyProject.Address' both use the XML type name, 'Address', from namespace ''. Use XML attributes to specify a unique XML name and/or namespace for the type..

结果消息:无法创建类MyCompany.MyProject.Test.AggregatorTests的实例。错误:System.TypeInitializationException:'MyCompany.MyProject.Test.AggregatorTests'的类型初始值设定项引发异常。 ---> System.InvalidOperationException:反映出类型为“MyCompany.MyProject.Root”的错误。 ---> System.InvalidOperationException:反映属性'ReportAReport'时出错。 ---> System.InvalidOperationException:反映出类型为“MyCompany.MyProject.ReportA.ReportAReport”的错误。 ---> System.InvalidOperationException:反映属性'Address'时出错。 ---> System.InvalidOperationException:出现反映类型'MyCompany.MyProject.ReportA.Address'的错误。 ---> System.InvalidOperationException:类型'MyCompany.MyProject.ReportA.Address'和'MyCompany.MyProject.Address'都使用来自命名空间''的XML类型名称'Address'。使用XML属性为类型指定唯一的XML名称和/或命名空间。

The line to which this exception is referring is as follows:

此异常所指的行如下:

XmlSerializer serializer = new XmlSerializer(typeof(Root));

The exception seems to be fairly clear about what is happening. The XmlSerializer is failing to understand to which Address class to map the property 'Address' in the ReportAReport class.

关于正在发生的事情似乎相当清楚。 XmlSerializer无法理解要在ReportAReport类中映射属性“Address”的Address类。

What I can't understand is why it is failing to understand to which Address class to map the property. In the class definition of ReportAReport, the 'Address' property is declared as being of type MyCompany.MyProject.ReportA.Address.

我无法理解的是为什么它无法理解要映射属性的Address类。在ReportAReport的类定义中,'Address'属性被声明为MyCompany.MyProject.ReportA.Address类型。

I even tried using XmlElementAttribute to specify the Type on ReportAReport:

我甚至尝试使用XmlElementAttribute在ReportAReport上指定Type:

[XmlElement(Type = typeof(Address))]
public Address Address { get; set; }

Though, that seems fairly redundant anyways...

虽然,这似乎相当多余......

Question

The compiler clearly knows that Address here is referring to MyCompany.MyProject.ReportA.Address. Why is the XmlSerializer unable to make this discernment?

编译器清楚地知道这里的Address是指MyCompany.MyProject.ReportA.Address。为什么XmlSerializer无法识别这个?

Shouldn't XmlSerializer know that if it encounters an Address node within a ReportAReport node, that it is of type MyCompany.MyProject.ReportA.Address rather than MyCompany.MyProject.Address?

XmlSerializer不应该知道如果它遇到ReportAReport节点中的Address节点,它的类型是MyCompany.MyProject.ReportA.Address而不是MyCompany.MyProject.Address吗?

What am I missing here?

我在这里想念的是什么?


I added the stack trace because it shows where the XmlSerializer initialization process is hiccuping. I actually pulled this stack trace from my real world example, which has a few nodes deeper than the samples, so there might be a few levels of recursion in the stack trace that don't seem to line up with the sample code I've provided.

我添加了堆栈跟踪,因为它显示了XmlSerializer初始化进程打嗝的位置。我实际上从我的真实世界示例中提取了这个堆栈跟踪,其中有几个节点比样本更深,因此堆栈跟踪中可能存在一些级别的递归,这些递归似乎与示例代码不符合我的情况提供。

Result StackTrace:  
at System.Xml.Serialization.XmlReflectionImporter.GetTypeMapping(String typeName, String ns, TypeDesc typeDesc, NameTable typeLib, Type type)
   at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.CreateArrayElementsFromAttributes(ArrayMapping arrayMapping, XmlArrayItemAttributes attributes, Type arrayElementType, String arrayElementNs, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportArrayLikeMapping(ArrayModel model, String ns, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.CreateArrayElementsFromAttributes(ArrayMapping arrayMapping, XmlArrayItemAttributes attributes, Type arrayElementType, String arrayElementNs, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportArrayLikeMapping(ArrayModel model, String ns, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
 --- End of inner exception stack trace ---
    at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportElement(TypeModel model, XmlRootAttribute root, String defaultNamespace, RecursionLimiter limiter)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type, XmlRootAttribute root, String defaultNamespace)
   at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
   at System.Xml.Serialization.XmlSerializer..ctor(Type type)
   at MyCompany.MyProject.Test.AggregatorTests..cctor() in c:\Users\crush\Documents\Visual Studio 2012\Projects\MyCompany.MyProject\Test\MyCompany.MyProject.Test\AggregatorTests.cs:line 16
 --- End of inner exception stack trace ---
    at MyCompany.MyProject.Test.AggregatorTests..ctor()

Update: I completely rewrote this question after realizing that my initial assessment about the exceptions I was receiving was completely incorrect. I negligently assumed that deserialization was the cause of the exception I was receiving, when in fact, it was clearly stated that initialization of the XmlSerializer was the problem. The question has been edited to state this fact, and I'm wiping the cake off my face as we speak. I apologize to anyone I misled with initial faulty and incomplete information.

更新:在我意识到我对收到的异常的初步评估完全不正确之后,我完全重写了这个问题。我疏忽地认为反序列化是我收到的异常的原因,事实上,有人明确指出XmlSerializer的初始化是个问题。这个问题已被编辑,以说明这一事实,我正在说话时,我正在擦掉脸上的蛋糕。我向任何误导最初错误和不完整信息的人道歉。

1 个解决方案

#1


0  

try this model to de-serialize against. You can instantiate a new Address of either type and set the value from the deserialized model. You could use AutoMapper to accomplish the copy of objects

尝试使用此模型进行反序列化。您可以实例化任一类型的新地址,并从反序列化模型中设置值。您可以使用AutoMapper来完成对象的复制

    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    public partial class Root
    {

        private RootAddress addressField;

        private RootReportAReport reportAReportField;

        /// <remarks/>
        public RootAddress Address
        {
            get
            {
                return this.addressField;
            }
            set
            {
                this.addressField = value;
            }
        }

        /// <remarks/>
        public RootReportAReport ReportAReport
        {
            get
            {
                return this.reportAReportField;
            }
            set
            {
                this.reportAReportField = value;
            }
        }
    }

    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class RootAddress
    {

        private ushort postalCodeField;

        /// <remarks/>
        public ushort PostalCode
        {
            get
            {
                return this.postalCodeField;
            }
            set
            {
                this.postalCodeField = value;
            }
        }
    }

    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class RootReportAReport
    {

        private RootReportAReportAddress addressField;

        /// <remarks/>
        public RootReportAReportAddress Address
        {
            get
            {
                return this.addressField;
            }
            set
            {
                this.addressField = value;
            }
        }
    }

    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class RootReportAReportAddress
    {

        private ushort zipField;

        /// <remarks/>
        public ushort Zip
        {
            get
            {
                return this.zipField;
            }
            set
            {
                this.zipField = value;
            }
        }
    }

#1


0  

try this model to de-serialize against. You can instantiate a new Address of either type and set the value from the deserialized model. You could use AutoMapper to accomplish the copy of objects

尝试使用此模型进行反序列化。您可以实例化任一类型的新地址,并从反序列化模型中设置值。您可以使用AutoMapper来完成对象的复制

    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    public partial class Root
    {

        private RootAddress addressField;

        private RootReportAReport reportAReportField;

        /// <remarks/>
        public RootAddress Address
        {
            get
            {
                return this.addressField;
            }
            set
            {
                this.addressField = value;
            }
        }

        /// <remarks/>
        public RootReportAReport ReportAReport
        {
            get
            {
                return this.reportAReportField;
            }
            set
            {
                this.reportAReportField = value;
            }
        }
    }

    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class RootAddress
    {

        private ushort postalCodeField;

        /// <remarks/>
        public ushort PostalCode
        {
            get
            {
                return this.postalCodeField;
            }
            set
            {
                this.postalCodeField = value;
            }
        }
    }

    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class RootReportAReport
    {

        private RootReportAReportAddress addressField;

        /// <remarks/>
        public RootReportAReportAddress Address
        {
            get
            {
                return this.addressField;
            }
            set
            {
                this.addressField = value;
            }
        }
    }

    /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class RootReportAReportAddress
    {

        private ushort zipField;

        /// <remarks/>
        public ushort Zip
        {
            get
            {
                return this.zipField;
            }
            set
            {
                this.zipField = value;
            }
        }
    }