使用CData部分包装属性 – XML序列化C#

我需要以这样的方式序列化我的对象,使我想要的属性绕过CData部分。 我希望我能做到这样的事情:

public class Order { [JsonProperty] public int OrderId { get; set; } [JsonProperty] public string Name { get; set; } [JsonProperty] public int Type { get; set; } [JsonProperty] public decimal Amount { get; set; } [JsonProperty] public DateTime Date { get; set; } [DataMember] [JsonProperty] **[WrapCData]** public List ListB { get; set; } [DataMember] public List ListC { get; set; } **[WrapCData]** public Product Product { get; set; } } 

是否有任何属性或实现可以将我的特定属性包装在CData部分周围? 现有的StackOverflow答案建议摆弄实体(类)本身。 这会变得非常混乱。

在以下主题中: 如何使用XmlSerializer将字符串序列化为CDATA?

菲利普的回答建议另一个财产及其相应的CData财产。 但是该属性是一个字符串。 CreateCDataSection()也接受一个字符串。 我需要在CDataSections周围包装我的自定义对象/列表。 我怎样才能做到这一点? 任何帮助,将不胜感激。 谢谢。

上述订单类的示例XML:

  2 Some Name 1 100 2015-12-07T15:10:49.6031106+05:00 <![CDATA[   OptionValue1 Option1   OptionValue2 Option2   ]]>  ListItem1 ListItem2  <![CDATA[  1 ProductName Product Type  ]]>  

通过一些努力和定制,可以接近您想要的,但XmlSerializer将始终将CData节点放在容器元素的末尾 。 您的示例XML显示容器元素的特定节点之间CData节点。 只要您不需要这种精确控制,就可以使用如何使用XmlSerializer将字符串序列化为CDATA? 做嵌套序列化,如下所示:

 public class Order { [JsonProperty] public int OrderId { get; set; } [JsonProperty] public string Name { get; set; } [JsonProperty] public int Type { get; set; } [JsonProperty] public decimal Amount { get; set; } [JsonProperty] public DateTime Date { get; set; } [DataMember] [JsonProperty] [XmlIgnore] // Do not serialize directly [XmlWrapCData] // Instead include in CDATA nodes public List 

使用以下扩展方法和自定义属性:

 [System.AttributeUsage(System.AttributeTargets.Property, AllowMultiple = false)] public class XmlWrapCDataAttribute : Attribute { public XmlWrapCDataAttribute() { this.Namespace = string.Empty; } public XmlWrapCDataAttribute(string name) : this() { this.Name = name; } public string Name { get; set; } public string Namespace { get; set; } } public static class XmlWrapCDataHelper { static Tuple [] XmlWrapCDataProperties(Type type) { return type.GetProperties() .Where(p => p.GetGetMethod() != null && p.GetSetMethod() != null) .Select(p => Tuple.Create(p, p.GetCustomAttribute())) .Where(p => p.Item2 != null) .ToArray(); } public static XmlNode[] GetCDataContent(object obj) { var index = new object[0]; var properties = XmlWrapCDataProperties(obj.GetType()); return properties.Select(p => (XmlNode)p.Item1.GetValue(obj, index).GetCData(p.Item2.Name ?? p.Item1.Name, p.Item2.Namespace)).ToArray(); } public static void SetCDataContent(object obj, XmlNode [] nodes) { if (nodes == null || nodes.Length < 1) return; var index = new object[0]; var properties = XmlWrapCDataProperties(obj.GetType()).ToDictionary(p => XName.Get(p.Item2.Name ?? p.Item1.Name, p.Item2.Namespace), p => p); var xml = "" + String.Concat(nodes.Select(c => c.Value)) + ""; foreach (var element in XElement.Parse(xml).Elements()) { Tuple pair; if (properties.TryGetValue(element.Name, out pair)) { var value = element.Deserialize(pair.Item1.PropertyType, element.Name.LocalName, element.Name.Namespace.NamespaceName); pair.Item1.SetValue(obj, value, index); } } } } public static class XmlSerializationHelper { public static XmlCDataSection GetCData(this object obj, string rootName, string rootNamespace) { return obj == null ? null : new System.Xml.XmlDocument().CreateCDataSection(obj.GetXml(XmlSerializerFactory.Create(obj.GetType(), rootName, rootNamespace))); } public static XCData GetCData(this object obj, XmlSerializer serializer = null) { return obj == null ? null : new XCData(obj.GetXml(serializer)); } public static string GetXml(this object obj, XmlSerializer serializer = null) { using (var textWriter = new StringWriter()) { var ns = new XmlSerializerNamespaces(); ns.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines. var settings = new XmlWriterSettings() { Indent = true, IndentChars = " ", OmitXmlDeclaration = true }; // For cosmetic purposes. using (var xmlWriter = XmlWriter.Create(textWriter, settings)) (serializer ?? new XmlSerializer(obj.GetType())).Serialize(xmlWriter, obj, ns); return textWriter.ToString(); } } public static object Deserialize(this XContainer element, Type type, string rootName = null, string rootNamespace = null) { return element.Deserialize(type, XmlSerializerFactory.Create(type, rootName, rootNamespace)); } public static object Deserialize(this XContainer element, Type type, XmlSerializer serializer = null) { using (var reader = element.CreateReader()) { return (serializer ?? new XmlSerializer(type)).Deserialize(reader); } } public static T DeserializeXML(this string xmlString, XmlSerializer serializer = null) { using (StringReader reader = new StringReader(xmlString)) { return (T)(serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader); } } } public static class XmlSerializerFactory { readonly static Dictionary, XmlSerializer> cache; readonly static object padlock; static XmlSerializerFactory() { padlock = new object(); cache = new Dictionary, XmlSerializer>(); } public static XmlSerializer Create(Type serializedType, string rootName, string rootNamespace) { if (serializedType == null) throw new ArgumentNullException(); if (rootName == null && rootNamespace == null) return new XmlSerializer(serializedType); lock (padlock) { XmlSerializer serializer; var key = Tuple.Create(serializedType, rootName, rootNamespace); if (!cache.TryGetValue(key, out serializer)) cache[key] = serializer = new XmlSerializer(serializedType, new XmlRootAttribute { ElementName = rootName, Namespace = rootNamespace }); return serializer; } } } 

这将成功解析您提供的XML,并返回生成如下所示的XML:

  2 Some Name 1 100 2015-12-07T05:10:49.6031106-05:00  ListItem1 ListItem2    ]]> 1 ProductName Product Type ]]>