简体   繁体   中英

dynamic Array object

I'm trying to build a generic method to convert objects into ExpandoObjects and I can handle all cases except when one of the properties is an array.

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

Any property that's an array doesn't seem to be a dynamic object and when I use it on something like a razor template the array elements and properties aren't visible.

For example, if I do this:

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

I get the following: VS Watch

As you can see the anonymous object at the top has an array of Students, but the converted ExpandoObject does not.

Does anyone have any insight on how I would change the code to add support for arrays/list in the ExpandoObject?

Thanks!

When you create an object like

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

LastName is a generic list and Property.PropertyType.IsArray returns false on that case. So your "array/list" is not treated with this logic that you are trying to add

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

Hope this helps

Just one remark, you don't need to check again inside the logic of the if(Property.Property.Type.IsArray) the Primitive values, you did it, that is one of the stop conditions of your recursion. Below is the same code with the difference that I am mentioning

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM