2017-02-23 3 views
1

Я хотел бы увидеть все свойства объекта, и мне бы хотелось, чтобы объект был распечатан. Что-то вроде perls Data::Dumper или php's var_dump.Пройдите объект, используя GetProperties

Я пробовал свой собственный код, но, наконец, попробовал это, что нашел в Интернете. Но каждый код выходит из строя на StackOverFlowException, вызванном объектом, имеющим ссылку на себя.

В примере ниже я пытаюсь напечатать объект CurrentThread, но который является классом типа Thread, который имеет свойство CurrentThread, которая указывает на тот же объект, и я застрял в бесконечном цикле.

Есть ли способ, уже находящийся в .Net, который я не знаю или как я могу попытаться решить эту проблему. Я думаю, что, возможно, у объекта/класса может быть ребенок, у которого есть родительское свойство, также вызывающее бесконечный цикл.

Так как существуют методы для сброса объекта на других языках, это, конечно, не первый раз, когда эти проблемы были обнаружены.

Как это можно решить?

Я хочу, чтобы все данные, которые будут распечатаны, а не только (в качестве примера):

obj.arr = string[] 

я бы необходимо:

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

Кто-нибудь есть хороший вход для меня?

EDIT: Я переписал пример: (старый код из оригинального вопроса ниже).

телефонный код:

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

OLD Пример:

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

Я сделал то же самое уже. Я решил эту проблему, имея HashSet, который содержит все ссылки, используя ObjectReferenceEqualityComparer (моя собственная реализация). Если вы найдете известную ссылочную печать «обратная ссылка на ». Распечатайте адрес указателя для каждого объекта. Имея это, вы можете искать этот pionter и находить свою информацию. –

+0

Спасибо за информацию, я немного переписал метод, чтобы получить лучший обзор, и я смогу добавить код позже. Но я все еще получаю исключение StackOverflowException. Какие-либо предложения? – MrApnea

ответ

0

Вы можете сделать простые и быстрые сериализации с помощью 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 
} 
+0

Спасибо, но я уже пробовал это. И это просто запускает ToString на все. Например, CurrentCulture имеет свойство KeyboardLayoutId. Это не показано здесь. Я хочу увидеть полный объект. – MrApnea

Смежные вопросы