繁体   English   中英

使用GetProperties遍历对象

[英]Traverse an object using GetProperties

我想看到一个对象的所有属性,我想看到一个对象打印出来。 像perls Data::Dumper或php的var_dump

我已经尝试了自己的代码,但最后尝试了我在网上找到的。 但是,每个代码都会因为对象具有对自身的引用而导致StackOverFlowException失败。

在下面的例子中,我试图打印出对象CurrentThread但这是一个类型为Thread的类,它有一个名为CurrentThread的属性,它指向同一个对象,我陷入无限循环。

.Net中是否存在一种我不知道的方法或者我将如何解决这个问题。 我在想,也许一个对象/类可能有一个具有父属性的子也会导致无限循环。

由于存在以其他语言转储对象的方法,这当然不是第一次检测到该问题。

怎么解决这个问题?

我希望打印出所有数据,而不仅仅是(作为示例):

obj.arr = string[]

我会需要:

obj.arr = ["a", "b"]

有没有人对我有任何好的意见?

编辑:我已经将示例重写为:(旧代码来自下面的原始问题)。

来电代码:

        var cache = new HashSet<object>();
        var sb = new StringBuilder();
        ParseObject(System.Threading.Thread.CurrentThread, 0, sb, cache);

方法:

private void ParseObject(object o, int level, StringBuilder sb, HashSet<object> cache) {
        if (o == null) {
            sb.Append("NULL");
            return;
        }

        var type = o.GetType();

        switch (type.FullName)
        {
            case "System.String":
                sb.Append(o).AppendLine();
                return;
            case "System.Int16":
            case "System.Int32":
            case "System.Int64":
                sb.Append(o).AppendLine();
                return;
            case "System.Single":
                sb.Append(o).AppendLine();
                return;
            case "System.Decimal":
                sb.Append(o).AppendLine();
                return;
            case "System.Double":
                sb.Append(o).AppendLine();
                return;
            case "System.DateTime":
                sb.Append(((DateTime)o).ToString("yyyy-MM-dd HH:mm:ss")).AppendLine();
                return;
        }

        if (cache.Contains(o))
        {
            sb.Append("REFERENCE TO OLD OBJECT");
            return;
        }
        cache.Add(o);

        if (o is IEnumerable<object>) {
            IEnumerable<object> io = o as IEnumerable<object>;
            int i = 0;
            foreach (object o1 in io) {
                sb.Append("[" + i + "] = ");
                ParseObject(o1, level+1, sb, cache);
            }
            return;
        }

        var hasProperties = false;
        foreach (PropertyInfo prop in type.GetProperties()) {
            hasProperties = true;
            sb.Append(new string('\t', level));
            sb.Append(prop.Name).Append("=");
            object element = prop.GetValue(o);
            ParseObject(element, level + 1, sb, cache);
        }

        if (!hasProperties) {
            sb.Append(o).AppendLine();
        }
    }

旧例子:

   var sb = new StringBuilder();
   PrintProperties(System.Threading.Thread.CurrentThread, 0, sb);

    public void PrintProperties(object obj, int indent, StringBuilder sb)
    {
        if (obj == null) return;
        string indentString = new string(' ', indent);
        Type objType = obj.GetType();
        PropertyInfo[] properties = objType.GetProperties();
        foreach (PropertyInfo property in properties)
        {
            object propValue = property.GetValue(obj, null);
            var elems = propValue as IList;
            if (elems != null)
            {
                foreach (var item in elems)
                {
                    PrintProperties(item, indent + 3, sb);
                }
            }
            else
            {
                // This will not cut-off System.Collections because of the first check
                if (property.PropertyType.Assembly == objType.Assembly)
                {
                    //Console.WriteLine("{0}{1}:", indentString, property.Name);
                    sb.AppendLine(string.Format("{0}{1}:", indentString, property.Name));

                    PrintProperties(propValue, indent + 2, sb);
                }
                else
                {
                    //Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
                    sb.AppendLine(string.Format("{0}{1}: {2}", indentString, property.Name, propValue));
                }
            }
        }
    }

您可以使用Json.Net进行简单快速的序列化

Console.WriteLine(JsonConvert.SerializeObject(
    System.Threading.Thread.CurrentThread,
    Formatting.Indented,
    new JsonSerializerSettings
    {
        ReferenceLoopHandling = ReferenceLoopHandling.Serialize
    }));

这将产生

{
  "ManagedThreadId": 9,
  "ExecutionContext": {},
  "Priority": 2,
  "IsAlive": true,
  "IsThreadPoolThread": false,
  "IsBackground": false,
  "ThreadState": 0,
  "ApartmentState": 1,
  "CurrentUICulture": "en-US",
  "CurrentCulture": "en-US",
  "Name": null
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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