C#反序列化XML报GenericPaymentMethod类型未识别异常
问题原因
反序列化抛出的中文异常为:InvalidOperationException: 指定类型无法识别: name='GenericPaymentMethod', namespace=''
触发原因有两个:
- XML中的
d2p1:type="GenericPaymentMethod"是XML标准的xsi:type属性(d2p1是http://www.w3.org/2001/XMLSchema-instance命名空间的临时前缀),作用是标记当前XML节点对应的实际运行时类型。XmlSerializer遇到该属性时,会查找和基类关联的、名称匹配的派生类型,当前代码没有注册对应派生类的映射,因此类型解析失败。 - 定义的
D2p1属性是冗余代码:xmlns:d2p1是XML命名空间声明,属于XML结构元数据,XmlSerializer会自动处理,不需要手动定义属性接收。
修复方案
按照以下步骤调整代码即可正常反序列化:
- 删除
PaymentMethod类中多余的D2p1属性。 - 在
PaymentMethod基类上添加[XmlInclude(typeof(GenericPaymentMethod))]特性,显式注册xsi:type对应的派生类型。 - 定义继承自
PaymentMethod的GenericPaymentMethod类,如果该类型没有额外专属字段,类体留空即可。
调整后的完整实体代码如下:
[Serializable, XmlRoot(ElementName = "PaymentMethod")] [XmlInclude(typeof(GenericPaymentMethod))] public class PaymentMethod { [XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")] public string Type { get; set; } [XmlElement(ElementName = "Amount")] public string Amount { get; set; } [XmlElement(ElementName = "CurrencyCode")] public string CurrencyCode { get; set; } [XmlElement(ElementName = "CurrencyCodeAlpha")] public string CurrencyCodeAlpha { get; set; } [XmlElement(ElementName = "AccountNumber")] public string AccountNumber { get; set; } [XmlElement(ElementName = "UtcExpiration")] public string UtcExpiration { get; set; } [XmlElement(ElementName = "PaymentMethodSubtype")] public string PaymentMethodSubtype { get; set; } [XmlElement(ElementName = "AccountHolderName")] public string AccountHolderName { get; set; } [XmlElement(ElementName = "QuotedAmount")] public string QuotedAmount { get; set; } [XmlElement(ElementName = "QuotedCurrencyCode")] public string QuotedCurrencyCode { get; set; } [XmlElement(ElementName = "QuotedCurrencyCodeAlpha")] public string QuotedCurrencyCodeAlpha { get; set; } [XmlElement(ElementName = "AccountNumberId")] public string AccountNumberId { get; set; } [XmlElement(ElementName = "TokenId")] public string TokenId { get; set; } } public class GenericPaymentMethod : PaymentMethod { }
临时处理方案:如果不需要做类型派生区分,只想快速把XML内容读入基类对象,可以在初始化
XmlTextReader读取XML流时设置Namespaces = false,忽略所有命名空间和xsi:type校验,不过该方案不符合XML序列化规范,仅适合临时数据处理场景。
内容的提问来源于stack exchange,提问作者lrac22
相关产品推荐
相关产品推荐

