You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

IXmlSerializable重命名元素后如何正确反序列化对应类型?

实现IXmlSerializable时,重命名XML元素后如何正确反序列化到真实类型?

问题场景

在实现IXmlSerializable接口时,已通过WriteXml方法将DataContext的序列化元素名从真实类型名(如ChartWindowViewModel)改为IViewModel,但在ReadXml方法中反序列化时,因XmlSerializer期望真实类型的元素名,导致抛出错误。

原实现代码

WriteXml代码

public void WriteXml(XmlWriter writer)
{
    XmlRootAttribute x = new XmlRootAttribute();          
    x.ElementName = nameof(IViewModel);
    var dwserializer = new XmlSerializer(this.DataContext.GetType(), x);
    dwserializer.Serialize(writer, this.DataContext);            
}

原ReadXml代码(存在问题)

public void ReadXml(XmlReader windowReader)
{
    var type = Type.GetType(windowReader.GetAttribute("AssemblyQualifiedName")); //此属性来自ViewModel序列化                          
    var dwserializer = new XmlSerializer(type);
    var a = dwserializer.Deserialize(windowReader); //因读取到重命名的"IViewModel"元素而抛出错误
}

XML示例

重命名后的XML

<Workspace Title="WS-001" NosWorkSpaceGuid="7f81ed2e-a511-4f9d-81db-9728304dad67">
    <ViewCollection>
        <ChartWindow AssemblyQualifiedName="CustomView.ChartWindow, ChartWindows, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" Top="78" Left="78" Height="1023" Width="2580">
            <IViewModel AssemblyQualifiedName="CustomView.ChartWindowViewModel, ChartWindows, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" Guid="606a4303-4662-4092-9c92-c452fb0f2860">
                <Conteners/>
            </IViewModel>
        </ChartWindow>
    </ViewCollection>
</Workspace>

未重命名时的XML(可正常工作)

<Workspace Title="WS-001" NosWorkSpaceGuid="08f17674-f7be-418a-a388-e3fc8796cb92">
    <ViewCollection>
        <ChartWindow AssemblyQualifiedName="CustomView.ChartWindow, ChartWindows, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" Top="226" Left="845" Height="1023" Width="2580">
            <ChartWindowViewModel AssemblyQualifiedName="CustomView.ChartWindowViewModel, ChartWindows, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" Guid="276d0b1b-e3d9-4067-a56e-ecc43faaa4e4">
                <Conteners/>
            </ChartWindowViewModel>
        </ChartWindow>
    </ViewCollection>
</Workspace>

解决方案

问题核心是:ReadXml中创建XmlSerializer时未指定与WriteXml一致的根元素名。修改时需同步指定XmlRootAttribute,让序列化器识别<IViewModel>元素。

修改后的ReadXml代码

public void ReadXml(XmlReader windowReader)
{
    // 获取真实类型
    var type = Type.GetType(windowReader.GetAttribute("AssemblyQualifiedName"));
    // 与WriteXml保持一致,指定根元素名为IViewModel
    var xmlRoot = new XmlRootAttribute(nameof(IViewModel));
    var dwserializer = new XmlSerializer(type, xmlRoot);
    // 反序列化得到真实类型实例
    var viewModel = dwserializer.Deserialize(windowReader);
    // 直接赋值给DataContext(若DataContext为IViewModel类型,无需强制转换)
    this.DataContext = viewModel;
    
    // 若需操作具体类型成员,可安全转换(可选)
    // var concreteViewModel = viewModel as ChartWindowViewModel;
    // if (concreteViewModel != null)
    // {
    //     // 处理具体类型逻辑
    // }
}

关键说明

  1. 同步根元素配置:必须在ReadXml中创建XmlSerializer时传入与WriteXml相同的XmlRootAttribute,确保序列化器能匹配<IViewModel>元素。
  2. 类型转换问题:反序列化得到的对象本身就是AssemblyQualifiedName指定的真实类型实例。如果DataContext是IViewModel接口类型,直接赋值即可;若需访问具体类型的专属成员,可使用as关键字进行安全转换,避免类型转换异常。

内容的提问来源于stack exchange,提问作者Zwan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 22:05:19