Puis-je sérialiser les types anonymes en xml?

J’ai compris que les types anonymes sont marqués comme privé par le compilateur et que les propriétés sont en lecture seule. Existe-t-il un moyen de les sérialiser au format xml (sans désérialiser)? Il fonctionne avec JSON , comment puis-je le faire avec XML?

Cela ne peut pas être accompli en utilisant XmlSerializer ni DataContractSerializer . Cela peut être fait par un code écrit manuellement, comme démontré ci-dessous (je ne peux pas dire si le code est suffisamment complet pour gérer tous les types – mais c’est un très bon début).

Quelque chose comme ça devrait vous aider à démarrer …

 class Program { static void Main(ssortingng[] args) { var me = new { Hello = "World", Other = new { My = "Object", V = 1, B = (byte)2 } }; var x = me.ToXml(); } } public static class Tools { private static readonly Type[] WriteTypes = new[] { typeof(ssortingng), typeof(DateTime), typeof(Enum), typeof(decimal), typeof(Guid), }; public static bool IsSimpleType(this Type type) { return type.IsPrimitive || WriteTypes.Contains(type); } public static XElement ToXml(this object input) { return input.ToXml(null); } public static XElement ToXml(this object input, ssortingng element) { if (input == null) return null; if (ssortingng.IsNullOrEmpty(element)) element = "object"; element = XmlConvert.EncodeName(element); var ret = new XElement(element); if (input != null) { var type = input.GetType(); var props = type.GetProperties(); var elements = from prop in props let name = XmlConvert.EncodeName(prop.Name) let val = prop.GetValue(input, null) let value = prop.PropertyType.IsSimpleType() ? new XElement(name, val) : val.ToXml(name) where value != null select value; ret.Add(elements); } return ret; } } 

… xml résultant …

  World  Object 1 2   

Merci, excellent travail @Matthew et @Martin.

J’ai apporté quelques modifications à Nullables et Enums. De plus, je l’ai changé pour que les éléments du tableau soient nommés en fonction du nom de la propriété + index.

Voici le code si quelqu’un est intéressé

 public static class ObjectExtensions { #region Private Fields private static readonly Type[] WriteTypes = new[] { typeof(ssortingng), typeof(DateTime), typeof(Enum), typeof(decimal), typeof(Guid), }; #endregion Private Fields #region .ToXml ///  /// Converts an anonymous type to an XElement. ///  /// The input. /// Returns the object as it's XML representation in an XElement. public static XElement ToXml(this object input) { return input.ToXml(null); } ///  /// Converts an anonymous type to an XElement. ///  /// The input. /// The element name. /// Returns the object as it's XML representation in an XElement. public static XElement ToXml(this object input, ssortingng element) { return _ToXml(input, element); } private static XElement _ToXml(object input, ssortingng element, int? arrayIndex = null, ssortingng arrayName = null) { if (input == null) return null; if (Ssortingng.IsNullOrEmpty(element)) { ssortingng name = input.GetType().Name; element = name.Contains("AnonymousType") ? "Object" : arrayIndex != null ? arrayName + "_" + arrayIndex : name; } element = XmlConvert.EncodeName(element); var ret = new XElement(element); if (input != null) { var type = input.GetType(); var props = type.GetProperties(); var elements = props.Select(p => { var pType = Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType; var name = XmlConvert.EncodeName(p.Name); var val = pType.IsArray ? "array" : p.GetValue(input, null); var value = pType.IsArray ? GetArrayElement(p, (Array)p.GetValue(input, null)) : pType.IsSimpleType() || pType.IsEnum ? new XElement(name, val) : val.ToXml(name); return value; }) .Where(v=>v !=null); ret.Add(elements); } return ret; } #region helpers ///  /// Gets the array element. ///  /// The property info. /// The input object. /// Returns an XElement with the array collection as child elements. private static XElement GetArrayElement(PropertyInfo info, Array input) { var name = XmlConvert.EncodeName(info.Name); XElement rootElement = new XElement(name); var arrayCount = input == null ? 0 : input.GetLength(0); for (int i = 0; i < arrayCount; i++) { var val = input.GetValue(i); XElement childElement = val.GetType().IsSimpleType() ? new XElement(name + "_" + i, val) : _ToXml(val, null, i, name); rootElement.Add(childElement); } return rootElement; } #region .IsSimpleType public static bool IsSimpleType(this Type type) { return type.IsPrimitive || WriteTypes.Contains(type); } #endregion .IsSimpleType #endregion helpers #endregion .ToXml } 

Ma propre version du travail alors excellent @Matthew et @Martin: Les tableaux de énumérations sont maintenant supportés et la notion de tableaux est généralisée dans IEnumerable afin de supporter également toutes sortes de collections.

 public static class ObjectExtensions { ///  /// Converts an anonymous type to an XElement. ///  /// The input. /// Returns the object as it's XML representation in an XElement. public static XElement ToXml2(this object input) { return input.ToXml2(null); } ///  /// Converts an anonymous type to an XElement. ///  /// The input. /// The element name. /// Returns the object as it's XML representation in an XElement. public static XElement ToXml2(this object input, ssortingng element) { return _ToXml(input, element); } private static XElement _ToXml(object input, ssortingng element, int? arrayIndex = null, ssortingng arrayName = null) { if (input == null) return null; if (Ssortingng.IsNullOrEmpty(element)) { ssortingng name = input.GetType().Name; element = name.Contains("AnonymousType") ? "Object" : arrayIndex != null ? arrayName + "_" + arrayIndex : name; } element = XmlConvert.EncodeName(element); var ret = new XElement(element); if (input != null) { var type = input.GetType(); var props = type.GetProperties(); var elements = props.Select(p => { var pType = Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType; var name = XmlConvert.EncodeName(p.Name); var val = pType.IsArray ? "array" : p.GetValue(input, null); var value = pType.IsEnumerable() ? GetEnumerableElements(p, (IEnumerable)p.GetValue(input, null)) : pType.IsSimpleType2() || pType.IsEnum ? new XElement(name, val) : val.ToXml2(name); return value; }) .Where(v=>v !=null); ret.Add(elements); } return ret; } #region helpers private static XElement GetEnumerableElements(PropertyInfo info, IEnumerable input) { var name = XmlConvert.EncodeName(info.Name); XElement rootElement = new XElement(name); int i = 0; foreach(var v in input) { XElement childElement = v.GetType().IsSimpleType2() || v.GetType().IsEnum ? new XElement(name + "_" + i, v) : _ToXml(v, null, i, name); rootElement.Add(childElement); i++; } return rootElement; } private static readonly Type[] WriteTypes = new[] { typeof(ssortingng), typeof(DateTime), typeof(Enum), typeof(decimal), typeof(Guid), }; public static bool IsSimpleType2(this Type type) { return type.IsPrimitive || WriteTypes.Contains(type); } private static readonly Type[] FlatternTypes = new[] { typeof(ssortingng) }; public static bool IsEnumerable(this Type type) { return typeof(IEnumerable).IsAssignableFrom(type) && !FlatternTypes.Contains(type); } #endregion } 

La réponse ci-dessous gère les IEnumerables de la manière dont j’en avais besoin et cela tournera ceci:

 new { Foo = new[] { new { Name = "One" }, new { Name = "Two" }, }, Bar = new[] { new { Name = "Three" }, new { Name = "Four" }, }, } 

dans ceci:

  One Two Three Four  

Alors voilà, une autre variante de la réponse de Matthew:

 public static class Tools { private static readonly Type[] WriteTypes = new[] { typeof(ssortingng), typeof(Enum), typeof(DateTime), typeof(DateTime?), typeof(DateTimeOffset), typeof(DateTimeOffset?), typeof(int), typeof(int?), typeof(decimal), typeof(decimal?), typeof(Guid), typeof(Guid?), }; public static bool IsSimpleType(this Type type) { return type.IsPrimitive || WriteTypes.Contains(type); } public static object ToXml(this object input) { return input.ToXml(null); } public static object ToXml(this object input, ssortingng element) { if (input == null) return null; if (ssortingng.IsNullOrEmpty(element)) element = "object"; element = XmlConvert.EncodeName(element); var ret = new XElement(element); if (input != null) { var type = input.GetType(); if (input is IEnumerable && !type.IsSimpleType()) { var elements = (input as IEnumerable) .Select(m => m.ToXml(element)) .ToArray(); return elements; } else { var props = type.GetProperties(); var elements = from prop in props let name = XmlConvert.EncodeName(prop.Name) let val = prop.GetValue(input, null) let value = prop.PropertyType.IsSimpleType() ? new XElement(name, val) : val.ToXml(name) where value != null select value; ret.Add(elements); } } return ret; } }