2017-02-23 7 views
1

オブジェクトのすべてのプロパティを表示したいと思います。オブジェクトを表示したいのですが。 perlのようなものData::Dumperまたはphpのvar_dumpGetPropertiesを使用してオブジェクトをトラバースする

私は自分のコードを試しましたが、最終的にこれを私がオンラインで見つけました。しかし、すべてのコードは、自身への参照を持つオブジェクトによって引き起こされるStackOverFlowExceptionで失敗します。

以下の例では、オブジェクトCurrentThreadを印刷しようとしていますが、これは同じオブジェクトを指す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(); 
     } 
    } 

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

を生成します。私はObjectReferenceEqualityComparer(私自身の実装)を使ってすべての参照を保持するHashSetを持つことで、このような問題を解決しました。あなたが既知のリファレンスプリントを見つけた場合は、 ""を参照してください。すべてのオブジェクトにポインタアドレスを出力します。これがあれば、その人を探してあなたの情報を見つけることができます。 –

+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

関連する問題