C#如何用XmlSerializer处理继承关系 @XmlInclude
发布时间 - 2025-12-31 00:00:00 点击率:次C# 中 XmlSerializer 不支持 Java 的 @XmlInclude 注解,但可用 XmlIncludeAttribute 特性(加在基类或容器类上)或 XmlAttributeOverrides 动态注册子类类型,以实现多态序列化。
在 C# 中,XmlSerializer 本身**不支持 @XmlInclude 注解**——这是 Java JAXB 的语法,C# 中没有这个特性。但你可以用等效的、C# 原生的方式实现相同目标:让 XmlSerializer 知道子类类型,从而正确序列化/反序列化继承结构。
使用 XmlAttributes 和 XmlAttributeOverrides 注册子类
这是最标准、最可靠的做法。你需要显式告诉 XmlSerializer 某个属性或字段可能包含哪些派生类型。
- 定义基类和子类(都需有无参构造函数)
- 创建
XmlAttributeOverrides实例 - 为基类中声明为基类类型的字段/属性,添加
XmlAttributes并设置XmlElements集合,加入每个允许的子类类型 - 用该 overrides 构造
XmlSerializer
示例:
public class Animal { public string Name { get; set; } }
public class Dog : Animal { public string Breed { get; set; } }
public class Cat : Animal { public bool IsIndoor { get; set; } }
public class Zoo
{
public Animal Pet { get; set; } // 基类引用,实际可能是 Dog 或 Cat
}
序列化时支持多态:
var overrides = new XmlAttributeOverrides();
var attrs = new XmlAttributes();
attrs.XmlElements.Add(new XmlElementAttribute("Dog", typeof(Dog)));
attrs.XmlElements.Add(new XmlElementAttribute("Cat", typeof(Cat)));
overrides.Add(typeof(Zoo), "Pet", attrs);
var serializer = new XmlSerializer(typeof(Zoo), overrides);
// 现在可正确序列化 Dog/Cat 到 或 元素中
在基类上用 XmlInclude 特性(推荐,更简洁)
C# 的 XmlIncludeAttribute 就是
对应 Java @XmlInclude 的功能,但它必须加在**基类或容器类上**,不能加在属性上。
- 加在基类上:表示该类型可能被其子类替代
- 加在持有基类引用的类(如容器类)上:表示该类中某些成员可能用到这些子类
继续上面的例子:
[XmlInclude(typeof(Dog))]
[XmlInclude(typeof(Cat))]
public class Animal
{
public string Name { get; set; }
}
// 或者加在 Zoo 上(效果等价)
[XmlInclude(typeof(Dog))]
[XmlInclude(typeof(Cat))]
public class Zoo
{
public Animal Pet { get; set; }
}
// 然后直接 new XmlSerializer(typeof(Zoo)) 即可,无需手动配置 overrides
注意:XmlInclude 是编译期静态注册,运行时无法动态增删类型。
反序列化时确保类型信息可识别
XmlSerializer 默认靠 XML 元素名区分类型(如 对应 Dog 类)。因此:
- 子类不要用
[XmlElement]改变根元素名,除非你同步在XmlInclude或XmlElementAttribute中指定相同名称 - 如果所有子类都序列化为同一名字(比如都叫
),则无法区分类型,会反序列化失败或丢失数据 - 必要时可用
[XmlType(TypeName = "Dog")]显式控制元素名
替代方案:考虑 DataContractSerializer(如需更灵活控制)
如果你需要类似 @XmlDiscriminator 的字段驱动类型识别(比如靠 XML 中某个 type="dog" 属性判断),XmlSerializer 不支持。此时可切换到 DataContractSerializer,配合 [KnownType] 和 ISerializable 自定义逻辑,但 XML 格式会不同(带命名空间、默认更冗长)。
不过对大多数场景,XmlInclude + 元素名区分已足够清晰且符合 XML 惯例。
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel如何处理JSON字段的查询和更新_Laravel JSON列操作与查询技巧
laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法
如何彻底卸载建站之星软件?
JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)
php做exe能调用系统命令吗_执行cmd指令实现方式【详解】
浅谈redis在项目中的应用
悟空浏览器如何设置小说背景色_悟空浏览器背景色设置【方法】
如何在 React 中条件性地遍历数组并渲染元素
创业网站制作流程,创业网站可靠吗?
网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?
如何在IIS中新建站点并配置端口与IP地址?
如何用PHP快速搭建高效网站?分步指南
Laravel如何使用Livewire构建动态组件?(入门代码)
为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】
JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)
高端网站建设与定制开发一站式解决方案 中企动力
详解Oracle修改字段类型方法总结
Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控
Midjourney怎么调整光影效果_Midjourney光影调整方法【指南】
Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用
使用PHP下载CSS文件中的所有图片【几行代码即可实现】
悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤
Swift中switch语句区间和元组模式匹配
独立制作一个网站多少钱,建立网站需要花多少钱?
Laravel Asset编译怎么配置_Laravel Vite前端构建工具使用
Laravel如何处理文件下载请求?(Response示例)
Microsoft Edge如何解决网页加载问题 Edge浏览器加载问题修复
三星、SK海力士获美批准:可向中国出口芯片制造设备
怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?
为什么php本地部署后css不生效_静态资源加载失败修复技巧【技巧】
如何在IIS7中新建站点?详细步骤解析
Laravel Blade模板引擎语法_Laravel Blade布局继承用法
Swift中循环语句中的转移语句 break 和 continue
高防服务器租用指南:配置选择与快速部署攻略
JavaScript Ajax实现异步通信
香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南
如何在橙子建站中快速调整背景颜色?
谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复
Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】
Laravel怎么实现支付功能_Laravel集成支付宝微信支付
Laravel怎么自定义错误页面_Laravel修改404和500页面模板
uc浏览器二维码扫描入口_uc浏览器扫码功能使用地址
详解CentOS6.5 安装 MySQL5.1.71的方法
,网页ppt怎么弄成自己的ppt?
免费网站制作appp,免费制作app哪个平台好?
Python图片处理进阶教程_Pillow滤镜与图像增强
如何在企业微信快速生成手机电脑官网?
Laravel如何记录日志_Laravel Logging系统配置与自定义日志通道
千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】
googleplay官方入口在哪里_Google Play官方商店快速入口指南

