使用.NET XSD.exe工具与XML序列化:Header元素实例化问题
解决XSD.exe生成类中Header属性未实例化的问题
我之前也踩过这个坑!xsd.exe生成的类型化类默认不会自动实例化嵌套的复杂类型属性,导致反序列化后访问MyDoc.Header.HeaderField这类子属性时直接触发空引用异常。这里分享几个实用的解决思路:
1. 修改生成的类,添加懒加载逻辑
直接在生成的Header属性的getter里做懒加载,只要访问这个属性就自动实例化:
// 替换生成的默认属性代码 private HeaderType _header; public HeaderType Header { get { if (_header == null) { _header = new HeaderType(); } return _header; } set { _header = value; } }
这种方式最直接,不管是序列化还是反序列化场景,只要访问Header就不会为空。唯一要注意的是,如果后续重新从XSD生成类,记得把这段逻辑重新加上,或者备份修改后的类。
2. 利用XmlSerializer的反序列化事件手动初始化
如果不想修改生成的类(避免重新生成时覆盖),可以绑定XmlSerializer的Deserialization事件,在反序列化完成后检查并实例化Header:
var serializer = new XmlSerializer(typeof(MyDoc)); // 绑定反序列化完成事件 serializer.Deserialization += (sender, e) => { var myDoc = e.Object as MyDoc; if (myDoc?.Header == null) { myDoc.Header = new HeaderType(); } }; // 执行反序列化操作 using var reader = new StreamReader("your-file.xml"); var doc = (MyDoc)serializer.Deserialize(reader);
这样就算生成的类没初始化Header,反序列化后也会自动补上,不会影响后续访问。
3. 在MyDoc的构造函数中初始化Header
如果是序列化(把对象转成XML)的场景,还可以直接在MyDoc的构造函数里初始化Header:
public MyDoc() { // 构造函数里直接实例化 this.Header = new HeaderType(); }
这样创建MyDoc对象时Header就已经存在,序列化时会自动输出对应的XML元素,也避免了后续访问时的空引用。
额外提示
如果你的项目需要频繁更新XSD,手动修改生成类太麻烦,可以考虑用第三方工具替代xsd.exe,这类工具通常支持配置自动生成嵌套类型的初始化代码,省掉不少重复工作。
内容的提问来源于stack exchange,提问作者Rob K.
相关产品推荐
相关产品推荐

