C#使用XmlMessageFormatter反序列化含嵌套内部类的XML失败求助
编辑
我在反序列化包含内部类(嵌套类)的XML文件时遇到问题。
我的类定义如下:
[XmlRoot(ElementName = "HM")] public class OwnClass : BaseClass{ ... public OwnClass(){} // 默认构造函数 ... }
我基于System.Messaging声明了如下_xmlMessageFormatter:
this._xmlMessageFormatter = new System.Messaging.XmlMessageFormatter(); System.Type[] OwnTypes = new System.Type[30]; OwnTypes[0] = typeof(Baseclasses.OwnClass); /* TR */ ... this._xmlMessageFormatter.TargetTypes = OwnTypes;
编辑:原XML格式如下:
<?xml version="1.0"?> <HM xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <ID>124</ID> <TC>TR</TC> </HM>
上述代码运行完全正常。
现在我在OwnClass的定义内新增了一个内部类:
[XmlRoot(ElementName = "HM")] public class OwnClass : BaseClass { [XmlElement(ElementName = "INS")] public ClassInside f_Inside; ... public OwnClass(){} // 默认构造函数 ... public class ClassInside{ ... public ClassInside(){} ...} // ClassInside定义结束 } // OwnClass定义结束
(注:原代码中构造函数多写的class关键字为笔误)
我也已经添加了对应的目标类型:
OwnTypes [27] = typeof(BaseClasses.OwnClass.ClassInside); // 数组下标正确。
编辑:修改后的XML格式如下:
<?xml version="1.0"?> <HM xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <ID>125</ID> <TC>TR</TC> <TR> <ID>1</ID> <CD>MOVE</CD> </TR> </HM>
此时_xmlMessageFormatter无法完成反序列化,相关代码如下:
源代码:
Object temp; temp = this._xmlMessageFormatter.Read(message);
为获取更多信息,我在Visual Studio的即时窗口输入? temp = this._xmlMessageFormatter.Read(message);,得到如下报错:
'temp = this._xmlMessageFormatter.Read(message)' threw an exception of type 'System.InvalidOperationException' Data: {System.Collections.ListDictionaryInternal} HResult: -2146233079 HelpLink: null InnerException: {"There was an error reflecting field 'f_Inside'."} Message: "There was an error reflecting type 'BaseClasses.AnotherClass'." Source: "System.Xml" StackTrace: " at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)\r\n at System.Xml.Serialization.XmlReflectionImporter.ImportElement(TypeModel model, XmlRootAttribute root, String defaultNamespace, RecursionLimiter limiter)\r\n at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type, XmlRootAttribute root, String defaultNamespace)\r\n at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)\r\n at System.Messaging.XmlMessageFormatter.CreateTargetSerializerTable()\r\n at System.Messaging.XmlMessageFormatter.Read(Message message)" TargetSite: {System.Xml.Serialization.TypeMapping ImportTypeMapping(System.Xml.Serialization.TypeModel, System.String, ImportContext, System.String, System.Xml.Serialization.XmlAttributes, Boolean, Boolean, System.Xml.Serialization.RecursionLimiter)}
我对报错信息存在两个疑问:
- 报错提到
f_Inside,看起来是对的,但我所有类都通用f_Inside作为字段名,这也引出第二个问题: - 我发送的是
OwnClass类型的消息,但报错却提到了AnotherClass。
我非常怀疑报错信息的准确性,请问有没有人知道我现在该怎么排查,或者_xmlFormatter的运行原理是什么?
编辑:补充背景信息
上述代码属于一个消息服务:一个应用发消息,另一个应用通过System.Messaging.MessageQueue对象接收,序列化/反序列化是其中的一个环节。
运行原理说明
XmlMessageFormatter在第一次调用Read方法时,会为TargetTypes数组中所有注册的类型预生成对应的XmlSerializer实例,生成过程中会递归扫描每个类型的所有公开字段、属性,校验序列化规则是否合法,只要任意一个类型校验失败就会直接抛出异常,和当前要反序列化的消息实际所属类型无关。这就是你发送OwnClass类型消息,却报AnotherClass错误的核心原因:全局扫描时先触发了AnotherClass的序列化规则校验失败。
排查和修复步骤
- 先修正
OwnClass的明显配置错误:你给f_Inside字段标注的[XmlElement(ElementName = "INS")]和XML中实际的<TR>节点名不匹配,把特性值改成ElementName = "TR",保证两边节点名一致。 - 修正代码语法错误:你贴的
ClassInside构造函数多写了class关键字,正确写法是public ClassInside(){},这个语法错误会直接导致反射失败。 - 排查所有带
f_Inside字段的类型,重点是报错提到的AnotherClass:- 确认它的内部类有public无参构造函数
- 确认内部类的所有公开字段/属性都是可序列化的类型,没有标注
[XmlIgnore]外的不可序列化特性 - 确认它的
f_Inside字段的Xml特性配置和对应XML结构匹配
- 缩小调试范围:临时把
AnotherClass从OwnTypes数组中移除,验证OwnClass的反序列化逻辑是否能正常运行,再逐步把其他类型加回去,快速定位问题类型。 - 单个类型快速验证:可以单独生成
XmlSerializer测试对应类型的反序列化逻辑,绕过XmlMessageFormatter的全局扫描,快速定位单个类型的问题:
// 测试OwnClass反序列化 string xmlContent = "这里填你要测试的XML字符串"; var serializer = new XmlSerializer(typeof(Baseclasses.OwnClass)); using (var reader = new StringReader(xmlContent)) { var result = serializer.Deserialize(reader); }
内容的提问来源于stack exchange,提问作者Dominique

