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

自定义XmlSerializer需求:仅序列化嵌套值类型及非空Nullable属性

针对你需要实现的这个仅序列化嵌套值类型属性的XmlSerializer,我整理了核心逻辑和代码示例,完全贴合你提到的规则:

核心序列化规则回顾

先明确我们要遵循的规则:

  • 值类型属性:直接序列化属性名称和对应的值
  • Nullable类型属性:仅当值非空时,序列化其Value属性;若值为空则跳过该属性
  • 类类型属性:目前需求未完善,我会在代码中预留扩展点,方便后续补充规则
自定义XmlSerializer实现

我们通过反射遍历对象属性,结合XmlWriter来生成符合要求的XML:

首先引用必要的命名空间:

using System;
using System.Xml;
using System.Reflection;

然后实现核心序列化类:

public class CustomXmlSerializer
{
    public string Serialize<T>(T obj)
    {
        if (obj == null)
            return string.Empty;

        // 配置XML格式:缩进、省略XML声明
        var settings = new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true };
        using (var stringWriter = new System.IO.StringWriter())
        using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
        {
            // 根元素用对象类型名称
            xmlWriter.WriteStartElement(typeof(T).Name);
            SerializeObject(obj, xmlWriter);
            xmlWriter.WriteEndElement();
            return stringWriter.ToString();
        }
    }

    private void SerializeObject(object obj, XmlWriter xmlWriter)
    {
        if (obj == null)
            return;

        Type type = obj.GetType();
        // 获取对象的所有公共实例属性
        PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);

        foreach (PropertyInfo prop in properties)
        {
            object propValue = prop.GetValue(obj);
            Type propType = prop.PropertyType;

            // 处理Nullable<T>类型
            if (propType.IsGenericType && propType.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                if (propValue != null)
                {
                    // 取出Nullable的Value值并序列化
                    object underlyingValue = propType.GetProperty("Value").GetValue(propValue);
                    xmlWriter.WriteElementString(prop.Name, underlyingValue.ToString());
                }
                // 值为空则跳过,不生成该元素
                continue;
            }

            // 处理值类型(已经排除Nullable,因为上面已单独处理)
            if (propType.IsValueType)
            {
                xmlWriter.WriteElementString(prop.Name, propValue.ToString());
                continue;
            }

            // 处理类类型(预留扩展点)
            // 目前逻辑是递归序列化类中的属性,你可以根据后续需求修改这里
            if (!propType.IsValueType && propType != typeof(string))
            {
                xmlWriter.WriteStartElement(prop.Name);
                SerializeObject(propValue, xmlWriter);
                xmlWriter.WriteEndElement();
            }
        }
    }
}
使用示例

我们定义一个包含各种类型属性的测试类,来验证序列化效果:

// 测试用的嵌套类
public class NestedData
{
    public decimal Price { get; set; }
    public int? StockCount { get; set; }
}

// 主测试类
public class Product
{
    public int Id { get; set; }
    public bool IsAvailable { get; set; }
    public double? Discount { get; set; }
    public string ProductName { get; set; } // 字符串是引用类型,当前逻辑下会生成空元素
    public NestedData Details { get; set; }
}

调用序列化的代码:

var product = new Product
{
    Id = 101,
    IsAvailable = true,
    Discount = 0.2,
    ProductName = "Wireless Headphones",
    Details = new NestedData { Price = 99.99m, StockCount = null }
};

var serializer = new CustomXmlSerializer();
string xmlResult = serializer.Serialize(product);
Console.WriteLine(xmlResult);

输出的XML结果:

<Product>
  <Id>101</Id>
  <IsAvailable>True</IsAvailable>
  <Discount>0.2</Discount>
  <ProductName>
  </ProductName>
  <Details>
    <Price>99.99</Price>
  </Details>
</Product>
类类型的扩展建议

如果后续你明确了类类型的序列化规则(比如仅序列化类内部的值类型/Nullable属性,跳过其他引用类型),可以修改类类型的处理逻辑,比如:

// 修改后的类类型处理逻辑
if (!propType.IsValueType && propType != typeof(string))
{
    if (propValue != null)
    {
        xmlWriter.WriteStartElement(prop.Name);
        SerializeObject(propValue, xmlWriter);
        xmlWriter.WriteEndElement();
    }
}

这样就能递归处理嵌套类中的值类型属性,同时忽略空的类对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:33:46