XML反序列化object类型属性后通过反射赋值到对应.NET类型的问题咨询
解决方案
方案1:调整XML序列化/反序列化规则,反序列化阶段直接生成目标类型
这是最优解,从根源避免后续转换操作,适合可以控制序列化逻辑的场景。
你当前反序列化得到字符串的核心原因是XML里Value节点的xsi:type固定为xsd:string,XmlSerializer会严格按照这个类型声明反序列化,只需要在序列化阶段就写入真实值的类型即可:
- 给
Value属性标注支持的序列化类型,或者构造XmlSerializer时传入所有可能用到的已知类型,示例修改如下:
[Serializable] public class SetpointPoint { [XmlAttribute] public string InstrumentName { get; set; } [XmlAttribute] public string Property { get; set; } // 声明所有可能用到的Value类型,XmlSerializer会自动处理xsi:type的读写 [XmlElement(Type = typeof(double)), XmlElement(Type = typeof(int)), XmlElement(Type = typeof(string)), XmlElement(Type = typeof(System.Drawing.Rectangle))] public object Value { get; set; } }
- 调整后序列化生成的XML会自动带上正确的类型声明,比如double类型的Value节点会变成:
<Value xsi:type="xsd:double">3</Value>
反序列化后Value属性就会是对应类型的对象,直接用你原来的反射赋值逻辑即可正常工作。
方案2:XML格式不可修改时,使用TypeConverter做通用类型转换
如果XML格式已经固定,只能拿到字符串格式的Value值,不需要手动逐个解析类型,.NET自带的TypeConverter机制已经覆盖了绝大多数框架内置类型的字符串转换逻辑,比Convert.ChangeType支持的类型范围广很多,包括Rectangle、Point这类结构都可以直接转换:
Dim ii = InstrumentLoader.Factory.GetNamed(point.InstrumentName) Dim pi = ii.GetType().GetProperty(point.Property) Dim tt = pi.PropertyType ' 获取目标类型的转换器 Dim converter = System.ComponentModel.TypeDescriptor.GetConverter(tt) If converter IsNot Nothing AndAlso converter.CanConvertFrom(point.Value.GetType()) Then Dim vt = converter.ConvertFrom(point.Value) pi.SetValue(ii, vt) Else ' 兜底走原有转换逻辑 Dim vt = Convert.ChangeType(point.Value, tt) pi.SetValue(ii, vt) End If
如果涉及自定义类型,只需要给类型加上TypeConverter特性并实现对应的转换逻辑,就可以复用这套通用转换代码,不需要修改赋值逻辑。
内容的提问来源于stack exchange,提问作者djv
相关产品推荐
相关产品推荐

