Can I serialize Anonymous Types as xml?

后端 未结 7 2060
误落风尘
误落风尘 2020-11-27 04:48

I understood that anonymous types are marked private by the compiler and the properties are read-only. Is there a way to serialize them to xml (without deserialize) ? It wor

7条回答
  •  猫巷女王i
    2020-11-27 05:25

    My own version of then excellent work @Matthew and @Martin : Arrays of enums are now supported and the notion of arrays in generalized into IEnumerable in order to also support all sort of 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, string element) {
        return _ToXml(input, element);
    }
    
    private static XElement _ToXml(object input, string element, int? arrayIndex = null, string arrayName = null) {
        if (input == null)
            return null;
    
        if (String.IsNullOrEmpty(element)) {
            string 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(string), 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(string)
    };
    public static bool IsEnumerable(this Type type) {
        return typeof(IEnumerable).IsAssignableFrom(type) && !FlatternTypes.Contains(type);
    }
    #endregion
    }
    

提交回复
热议问题