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

C#无XmlAttributes泛型反序列化XML列表:对象值为空

解决无XmlAttributes的泛型XML属性反序列化问题

我懂你现在的困扰——你想做一个通用的XML反序列化工具,不用在实体类上加XmlAttributes,但现在虽然能拿到3个Item对象,所有属性都是默认值(0、null)对吧?

问题根源

你当前用的XmlSerializer默认行为是映射XML元素到类属性,但你的XML里的ItemId、ItemName这些都是XML节点的属性(就是<Item ItemId="1">里的键值对),所以默认的序列化器根本不会读取这些属性值,自然就填充默认值了。

通用解决方案:反射+XElement手动映射

既然要通用性,我们可以用反射来遍历XML节点的属性,然后手动映射到类的对应属性上,完全不需要加任何特性。

改进后的完整代码

private XDocument sourceData; // 假设这个已经被正确初始化

public List<T> GetObjectList<T>(string identifier) where T : class, new()
{
    if (sourceData == null || string.IsNullOrEmpty(identifier))
        return new List<T>();

    // 直接遍历指定名称的节点,映射到对象
    return sourceData.Descendants(identifier)
                     .Select(MapXmlAttributesToObject<T>)
                     .ToList();
}

private T MapXmlAttributesToObject<T>(XElement element) where T : class, new()
{
    var targetObj = new T();
    var targetType = typeof(T);

    foreach (var xmlAttr in element.Attributes())
    {
        // 找到类中匹配的属性(支持大小写不敏感,可根据需求调整)
        var targetProperty = targetType.GetProperty(
            xmlAttr.Name.LocalName,
            BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase
        );

        if (targetProperty == null)
            continue; // 找不到对应属性就跳过

        // 处理值转换,包括可空类型
        try
        {
            object propertyValue;
            var nullableUnderlyingType = Nullable.GetUnderlyingType(targetProperty.PropertyType);
            
            // 处理可空类型+空字符串的情况
            if (nullableUnderlyingType != null && string.IsNullOrEmpty(xmlAttr.Value))
            {
                propertyValue = null;
            }
            else
            {
                // 转换值到目标类型(包括非可空类型)
                propertyValue = Convert.ChangeType(
                    xmlAttr.Value,
                    nullableUnderlyingType ?? targetProperty.PropertyType
                );
            }

            targetProperty.SetValue(targetObj, propertyValue);
        }
        catch
        {
            // 转换失败时可以记录日志,这里简单跳过
            continue;
        }
    }

    return targetObj;
}

// 你的Item类保持不变
public class Item
{
    public int ItemId { get; set; }
    public string ItemName { get; set; }
    public int? Number { get; set;}
    public DateTime? Created { get; set; }
}

调用方式

// 假设xml是你的XML字符串
sourceData = XDocument.Parse(xml);
var itemList = GetObjectList<Item>("Item");

为什么这个方案能工作?

  1. 直接操作XElement:避免了把节点转成字符串再反序列化的低效操作,直接读取XML属性。
  2. 反射映射:通过反射动态找到类的属性,和XML属性名称匹配(支持大小写不敏感,适合不同XML的命名风格)。
  3. 处理可空类型:专门判断了可空类型(比如int?、DateTime?)和空字符串的情况,确保空值能正确映射为null。
  4. 完全通用:不管你传入什么T类型,只要属性名称和XML属性对应,就能自动完成映射,不需要加任何XmlAttribute或XmlElement特性。

验证结果

运行后你会得到正确的Item对象:

  • ItemId分别为1、2、3
  • ItemName分别为TestName1、TestName2、TestName3
  • Number分别为100、200、300
  • Created均为null(因为XML里是空字符串)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:29:03