Итерация по ExpandoObject создает исключение StackOverflowException - PullRequest
1 голос
/ 03 февраля 2020

У меня есть экспло, как

dynamic x = new ExpandoObject ();

AddProperty (x, "Name", "Nick");
AddProperty (x, "Seat", "8H");
AddProperty (x, "Code", "11");

Console.WriteLine(x.Name);
Console.WriteLine (x.Seat);
Console.WriteLine (x.Code);

, и я использую метод AddProperty для вышеупомянутого, в соответствии с найденным источником, то есть

public static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
{
     // ExpandoObject supports IDictionary so we can extend it like this
     var expandoDict = expando as IDictionary<string, object>;

     if ( expandoDict.ContainsKey (propertyName) )
         expandoDict[propertyName] = propertyValue;
     else
         expandoDict.Add (propertyName, propertyValue);
}

Теперь я использую этот метод для перебирать мои классы (и это работает, даже для связанных классов, то есть для свойств, которые определены с использованием других классов, например publi c anotherClass address {get; set;} et c ..), и до сих пор работает нормально :

private static void IterateThrough(object source)
{
    Type sourceType = source.GetType(); //Get current object type of source

    //Iterate through all properties of the source object
    foreach (PropertyInfo prop in sourceType.GetProperties
    (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
    {
        var Type = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;

        if (prop.PropertyType.IsClass && prop.PropertyType != typeof(string)) {
            object o = prop.GetValue(source, null);
            IterateThrough(o);
        }

        Console.WriteLine(prop.DeclaringType.Name + "." + prop.Name);
    }
}

Однако, когда я пытаюсь с расширением, я получаю ошибку длины массива и переполнение стека в конечном итоге.

В чем ошибка, и как правильно выполнить итерацию по моим объектам, чтобы он мог работать как для «нормальных» классов, так и для моего расширения?

1 Ответ

1 голос
/ 03 февраля 2020

С общей точки зрения, StackOverflowException вызвано рекурсией в пределах IterateThrough.

Более актуально для вашего контекста, хотя класс ExpandoObject реализует IDictionary<string, object> для своих свойств, поэтому решение состоит в том, чтобы использовать приведение вместо отражения:

IDictionary<string, object> propertyValues = (IDictionary<string, object>) source;

Ваш IterateThrough Метод может иметь такую ​​проверку:

if (source is IDictionary<string, object>){
    IDictionary<string, object> propertyValues = (IDictionary<string, object>) source;

    //iterate through your values
}
else{
    //your existing code
}

Однако вы можете обнаружить, что ваш существующий код будет ломаться и с другими типами объектов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...