【问题标题】:dynamic Array object动态数组对象
【发布时间】:2015-11-25 04:27:36
【问题描述】:

我正在尝试构建一个通用方法来将对象转换为 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 中添加对数组/列表的支持?

谢谢!

【问题讨论】:

标签: c# .net expandoobject


【解决方案1】:

当你创建像这样的对象时

var person = new
            {
                FirstName = "Test",
                LastName = new List<Person>() { new Person()
                {
                    FirstName = "Tes2"                    
                } }
            };

LastName 是一个通用列表,Property.PropertyType.IsArray 在这种情况下返回 false。因此,您的“数组/列表”不会被您尝试添加的逻辑处理

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;
        }

【讨论】:

  • 感谢您的回复 Zinov。我实际上是在列表上明确调用 .ToArray() ,所以这不应该是一个问题。在调试时,我已经确认 Property.PropertyType.IsArray 实际上是正确的。
  • 你能把你的例子的输入数据放上去吗?
  • 我刚刚添加了一个示例
  • 也许你很困惑,我运行代码,显然你在 ExpandoObject 上拥有所有属性。您正在尝试通过 DynamicView 将它们可视化,这将只获取该对象的动态成员,ResultView 是迭代所有 IEnumerable 成员的对象,尝试展开 ResultView 并在内部您将看到带有列表的属性所有的价值观。我在我的回答中添加了关于处理数组的特定代码的评论
猜你喜欢
  • 2021-01-30
  • 2015-06-03
  • 2010-09-20
  • 2011-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多