объект динамического массива

Я пытаюсь создать общий метод для преобразования объектов в 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"} }
        };

Получаю следующее:  VS Watch

Как вы можете видеть, анонимный объект вверху имеет массив студентов, а преобразованный ExpandoObject - нет.

Есть ли у кого-нибудь представление о том, как я могу изменить код, чтобы добавить поддержку массивов / списка в ExpandoObject?

Спасибо!


person Lambo Jayapalan    schedule 25.11.2015    source источник
comment
возможно, вам понадобится этот проект: github.com/chsword/jdynamic   -  person chsword    schedule 25.11.2015


Ответы (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) примитивных значений, вы это сделали, это одно из условий остановки вашей рекурсии. Ниже приведен тот же код с той разницей, о которой я упоминаю.

 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;
        }
person Zinov    schedule 25.11.2015
comment
Спасибо за ответ Зинов. Я на самом деле вызываю .ToArray () явно в списке, так что это не должно быть проблемой. И во время отладки я подтвердил, что Property.PropertyType.IsArray действительно соответствует действительности. - person Lambo Jayapalan; 25.11.2015
comment
Можете выложить исходные данные вашего примера? - person Zinov; 25.11.2015
comment
Я только что добавил пример - person Lambo Jayapalan; 26.11.2015
comment
Возможно, вы запутались, я запускаю код и ясно, что у вас есть все свойства ExpandoObject. Вы пытаетесь визуализировать их через DynamicView, и он получит только динамические члены для этого объекта, ResultView - это тот, который выполняет итерацию по всем членам, которые являются IEnumerable, попробуйте развернуть ResultView, и внутри вы увидите свое свойство со списком с все ценности. Я добавляю в свой ответ комментарий о конкретном коде, обрабатывающем массив - person Zinov; 01.12.2015