自定义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
相关产品推荐
相关产品推荐

