如何在XmlSerializer中使用带动态值参数的泛型类型?
你的实现方式完全不可行,核心问题有两个:
- C#泛型参数仅支持类型参数,不能直接传入具体值(比如
TsResponse<T, string myNodeName>这种写法是语法错误,编译器会直接报错)。 [XmlElement]特性的参数必须是编译时常量,无法通过泛型参数动态传递节点名称。
正确实现方案
方案一:用XmlAttributeOverrides动态指定节点名(推荐,支持运行时动态节点名)
这种方式可以在创建XmlSerializer时,动态覆盖属性对应的XML节点名称,完美适配API返回的动态节点名场景。
// 修正泛型类定义,移除错误的泛型值参数 [XmlRoot("tsResponse")] public class TsResponse<T> { // 先定义默认节点名,后续会动态覆盖 [XmlElement("default_node")] public T Object { get; set; } } public class User { [XmlAttribute("id")] public string Id { get; set; } } // 反序列化调用代码 string xml = @"<tsResponse> <value id=""hello""/> </tsResponse>"; // 创建属性覆盖配置:指定TsResponse<User>的Object属性对应XML节点名为"value" XmlAttributeOverrides overrides = new XmlAttributeOverrides(); XmlAttributes attrs = new XmlAttributes(); attrs.XmlElements.Add(new XmlElementAttribute("value")); overrides.Add(typeof(TsResponse<User>), nameof(TsResponse<User>.Object), attrs); // 使用带覆盖配置的XmlSerializer完成反序列化 using (StringReader sr = new StringReader(xml)) { XmlSerializer serializer = new XmlSerializer(typeof(TsResponse<User>), overrides); TsResponse<User> responseXml = (TsResponse<User>)serializer.Deserialize(sr); // 此时responseXml.Object.Id的值为"hello" }
方案二:创建子类固定节点名(适合节点名有限的场景)
如果API返回的节点名只有固定几种(比如仅"value"、"data"),可以为每种节点名创建对应的子类:
[XmlRoot("tsResponse")] public class TsResponse<T> { public T Object { get; set; } } // 针对"value"节点的子类 public class TsValueResponse<T> : TsResponse<T> { [XmlElement("value")] public new T Object { get; set; } } public class User { [XmlAttribute("id")] public string Id { get; set; } } // 反序列化调用代码 using (StringReader sr = new StringReader(xml)) { XmlSerializer serializer = new XmlSerializer(typeof(TsValueResponse<User>)); TsValueResponse<User> responseXml = (TsValueResponse<User>)serializer.Deserialize(sr); }
内容的提问来源于stack exchange,提问作者thibsc
相关产品推荐
相关产品推荐

