遍历ExpandoObject会引发StackOverflowException

时间:2020-02-02 22:32:17

标签: c# loops properties expandoobject

我有一个expando,例如

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

现在,我使用此方法遍历我的类(并且即使对于链接的类,也可以使用它,即对于使用其他类定义的属性(例如,公共anotherClass地址{get; set;}等)也有效),它到目前为止效果很好:

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

但是,当我尝试使用expando时,会出现数组长度错误并最终导致堆栈溢出。

有什么错误,我该如何正确遍历对象,以便它可以在“常规”案例类和我的expando上运行?

1 个答案:

答案 0 :(得分:1)

从一般的角度来看,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
}

但是,您可能会发现现有代码也会与其他类型的对象一起中断。