动态数组对象

dynamic Array object

我正在尝试构建一个将对象转换为 ExpandoObjects 的通用方法,我可以处理所有情况,除非其中一个属性是数组。

    public static ExpandoObject ToExpando(this object AnonymousObject) {
        dynamic NewExpando = new ExpandoObject();
        foreach (var Property in AnonymousObject.GetType().GetProperties()) {
            dynamic Value;
            if (IsPrimitive(Property.PropertyType)) {
                Value = Property.GetValue(AnonymousObject);
            } else if (Property.PropertyType.IsArray) {
                dynamic ArrayProperty = new List<dynamic>();
                var ArrayElements = (Array)Property.GetValue(AnonymousObject);
                for (var i = 0; i < ArrayElements.Length; i++) {
                    var Element = ArrayElements.GetValue(i);
                    if (IsPrimitive(Element.GetType())) {
                        ArrayProperty.Add(Element);
                    } else {
                        ArrayProperty.Add(ToExpando(Element));
                    }
                }

                Value = ArrayProperty;//.ToArray();
            } else {
                Value = ToExpando(Property.GetValue(AnonymousObject));
            }
            ((IDictionary<string, object>) NewExpando)[Property.Name] = Value;
        }
        return NewExpando;
    }

    private static bool IsPrimitive(System.Type type) {
        while (type.IsGenericType && type.GetGenericTypeDefinition() == typeof (Nullable<>)) {
            // nullable type, check if the nested type is simple.
            type = type.GetGenericArguments()[0];
        }
        return type.IsPrimitive || type.IsEnum || type.Equals(typeof (string)) || type.Equals(typeof (decimal));
    }

任何 属性 数组似乎都不是动态对象,当我在剃刀模板之类的东西上使用它时,数组元素和属性不可见。

例如,如果我这样做:

var EmailParams = new {
            Parent = new {
                Username = "User1",
            },
            Students = new [] {new {Username = "Student1", Password = "Pass1"} }
        };

我得到以下信息:

如您所见,顶部的匿名对象有一个学生数组,但转换后的 ExpandoObject 没有。

有人知道我将如何更改代码以在 ExpandoObject 中添加对 arrays/list 的支持吗?

谢谢!

当你创建一个像

这样的对象时
var person = new
            {
                FirstName = "Test",
                LastName = new List<Person>() { new Person()
                {
                    FirstName = "Tes2"                    
                } }
            };

LastName 是一个通用列表,Property.PropertyType.IsArray returns 在这种情况下为 false。所以你的 "array/list" 没有被你试图添加的逻辑处理

dynamic ArrayProperty = new List<dynamic>();
                var ArrayElements = (Array)Property.GetValue(AnonymousObject);
                for (var i = 0; i < ArrayElements.Length; i++) {
                    var Element = ArrayElements.GetValue(i);
                    if (IsPrimitive(Element.GetType())) {
                        ArrayProperty.Add(Element);
                    } else {
                        ArrayProperty.Add(ToExpando(Element));
                    }
                }

希望对您有所帮助

只是一句话,你不需要再次检查 if(Property.Property.Type.IsArray) Primitive 值的逻辑,你做到了,这是你递归的停止条件之一。下面是相同的代码,不同之处在于我提到的

 public static ExpandoObject ToExpando(this object AnonymousObject)
        {
            dynamic NewExpando = new ExpandoObject();
            foreach (var Property in AnonymousObject.GetType().GetProperties())
            {
                dynamic Value;
                if (IsPrimitive(Property.PropertyType))
                {
                    Value = Property.GetValue(AnonymousObject);
                }
                else if (Property.PropertyType.IsArray)
                {
                    var ArrayProperty = new List<ExpandoObject>();
                    var elements = Property.GetValue(AnonymousObject) as IEnumerable;

                    //is the same as foreach all elements calling to Expando and adding them to elemenstArray
                    if (elements != null)
                        ArrayProperty.AddRange(from object elem in elements select ToExpando(elem));

                    Value = ArrayProperty;
                }
                else
                {
                    Value = ToExpando(Property.GetValue(AnonymousObject));
                }
                ((IDictionary<string, object>)NewExpando)[Property.Name] = Value;
            }
            return NewExpando;
        }