简体   繁体   English

使用GetProperties遍历对象

[英]Traverse an object using GetProperties

I would like to see all properties on an object and i would like to see an object printed out. 我想看到一个对象的所有属性,我想看到一个对象打印出来。 Something like perls Data::Dumper or php's var_dump . 像perls Data::Dumper或php的var_dump

I have tried my own code but finally tried this that i found online. 我已经尝试了自己的代码,但最后尝试了我在网上找到的。 But every code fails on StackOverFlowException caused by an object having a reference to itself. 但是,每个代码都会因为对象具有对自身的引用而导致StackOverFlowException失败。

In the example below i am trying to print out the object CurrentThread but that is a class of type Thread which has a property called CurrentThread which points to the same object and i am stuck in an endless loop. 在下面的例子中,我试图打印出对象CurrentThread但这是一个类型为Thread的类,它有一个名为CurrentThread的属性,它指向同一个对象,我陷入无限循环。

Is there a method already in .Net that i don't know about or how sould i try to solve this. .Net中是否存在一种我不知道的方法或者我将如何解决这个问题。 I am thinking that maybe an object/class could have a child which has a parent property also causing an endless loop. 我在想,也许一个对象/类可能有一个具有父属性的子也会导致无限循环。

Since there are methods for dumping an object in other languages this is of course not the first time this probles has been detected. 由于存在以其他语言转储对象的方法,这当然不是第一次检测到该问题。

How can this be solved? 怎么解决这个问题?

I want all data to be printed out, not just (as an example): 我希望打印出所有数据,而不仅仅是(作为示例):

obj.arr = string[]

i would need: 我会需要:

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

Does anyone have any good input for me? 有没有人对我有任何好的意见?

EDIT: I have rewritten the example into this: (old code from orginal question below). 编辑:我已经将示例重写为:(旧代码来自下面的原始问题)。

Calling code: 来电代码:

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

Method: 方法:

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

OLD Example: 旧例子:

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

You can do a simple and fast serialization using Json.Net 您可以使用Json.Net进行简单快速的序列化

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

This will produce 这将产生

{
  "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