object dumper class

岁酱吖の 提交于 2019-11-26 17:10:12

The object dumper posted in sgmoore's link:

//Copyright (C) Microsoft Corporation.  All rights reserved.

using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

// See the ReadMe.html for additional information
public class ObjectDumper {

    public static void Write(object element)
    {
        Write(element, 0);
    }

    public static void Write(object element, int depth)
    {
        Write(element, depth, Console.Out);
    }

    public static void Write(object element, int depth, TextWriter log)
    {
        ObjectDumper dumper = new ObjectDumper(depth);
        dumper.writer = log;
        dumper.WriteObject(null, element);
    }

    TextWriter writer;
    int pos;
    int level;
    int depth;

    private ObjectDumper(int depth)
    {
        this.depth = depth;
    }

    private void Write(string s)
    {
        if (s != null) {
            writer.Write(s);
            pos += s.Length;
        }
    }

    private void WriteIndent()
    {
        for (int i = 0; i < level; i++) writer.Write("  ");
    }

    private void WriteLine()
    {
        writer.WriteLine();
        pos = 0;
    }

    private void WriteTab()
    {
        Write("  ");
        while (pos % 8 != 0) Write(" ");
    }

    private void WriteObject(string prefix, object element)
    {
        if (element == null || element is ValueType || element is string) {
            WriteIndent();
            Write(prefix);
            WriteValue(element);
            WriteLine();
        }
        else {
            IEnumerable enumerableElement = element as IEnumerable;
            if (enumerableElement != null) {
                foreach (object item in enumerableElement) {
                    if (item is IEnumerable && !(item is string)) {
                        WriteIndent();
                        Write(prefix);
                        Write("...");
                        WriteLine();
                        if (level < depth) {
                            level++;
                            WriteObject(prefix, item);
                            level--;
                        }
                    }
                    else {
                        WriteObject(prefix, item);
                    }
                }
            }
            else {
                MemberInfo[] members = element.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance);
                WriteIndent();
                Write(prefix);
                bool propWritten = false;
                foreach (MemberInfo m in members) {
                    FieldInfo f = m as FieldInfo;
                    PropertyInfo p = m as PropertyInfo;
                    if (f != null || p != null) {
                        if (propWritten) {
                            WriteTab();
                        }
                        else {
                            propWritten = true;
                        }
                        Write(m.Name);
                        Write("=");
                        Type t = f != null ? f.FieldType : p.PropertyType;
                        if (t.IsValueType || t == typeof(string)) {
                            WriteValue(f != null ? f.GetValue(element) : p.GetValue(element, null));
                        }
                        else {
                            if (typeof(IEnumerable).IsAssignableFrom(t)) {
                                Write("...");
                            }
                            else {
                                Write("{ }");
                            }
                        }
                    }
                }
                if (propWritten) WriteLine();
                if (level < depth) {
                    foreach (MemberInfo m in members) {
                        FieldInfo f = m as FieldInfo;
                        PropertyInfo p = m as PropertyInfo;
                        if (f != null || p != null) {
                            Type t = f != null ? f.FieldType : p.PropertyType;
                            if (!(t.IsValueType || t == typeof(string))) {
                                object value = f != null ? f.GetValue(element) : p.GetValue(element, null);
                                if (value != null) {
                                    level++;
                                    WriteObject(m.Name + ": ", value);
                                    level--;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    private void WriteValue(object o)
    {
        if (o == null) {
            Write("null");
        }
        else if (o is DateTime) {
            Write(((DateTime)o).ToShortDateString());
        }
        else if (o is ValueType || o is string) {
            Write(o.ToString());
        }
        else if (o is IEnumerable) {
            Write("...");
        }
        else {
            Write("{ }");
        }
    }
}

2015 Update

YAML also serves this purpose quite well, this is how it can be done with YamlDotNet

install-package YamlDotNet

    private static void DumpAsYaml(object o)
    {
        var stringBuilder = new StringBuilder();
        var serializer = new Serializer();
        serializer.Serialize(new IndentedTextWriter(new StringWriter(stringBuilder)), o);
        Console.WriteLine(stringBuilder);
    }

You could use the JSON serialiser, which should be easy to read for anyone use to working with JSON

User theUser = new User();
theUser.Name = "Joe";
System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(myPerson.GetType());
MemoryStream ms = new MemoryStream();
serializer.WriteObject(ms, theUser );
string json = Encoding.Default.GetString(ms.ToArray()); 
Dan Diplo

Updated 2019

You can find the ObjectDumper project on GitHub. You can also add it via Visual Studio via NuGet package manager.

If you're working with markup, System.Web.ObjectInfo.Print (ASP.NET Web Pages 2) will accomplish this, nicely formatted for HTML.

For example:

@ObjectInfo.Print(new {
    Foo = "Hello",
    Bar = "World",
    Qux = new {
        Number = 42,
    },
})

In a webpage, produces:

Here's a visual studio extension I wrote to do this:

https://visualstudiogallery.msdn.microsoft.com/c6a21c68-f815-4895-999f-cd0885d8774f

in action:

I know this is an old question, but thought I'd throw out an alternative that worked for me, took me about two minutes to do.

Install Newtonsoft Json.NET: http://james.newtonking.com/json

(or nuget version) http://www.nuget.org/packages/newtonsoft.json/

Reference Assembly:

using Newtonsoft.Json;

Dump JSON string to log:

txtResult.Text = JsonConvert.SerializeObject(testObj);

You could write that very easily with a little bit of reflection. Something kind of like:

public void Print(object value, int depth)
{
    foreach(var property in value.GetType().GetProperties())
    {
        var subValue = property.GetValue(value);
        if(subValue is IEnumerable)
        {
             PrintArray(property, (IEnumerable)subValue);
        }
        else
        {
             PrintProperty(property, subValue);
        }         
    }
}

You can write up the PrintArray and PrintProperty methods.

I have a handy T.Dump() Extension method that should be pretty close to the results you're looking for. As its an extension method, its non-invasive and should work on all POCO objects.

Example Usage

var model = new TestModel();
Console.WriteLine(model.Dump());

Example Output

{
    Int: 1,
    String: One,
    DateTime: 2010-04-11,
    Guid: c050437f6fcd46be9b2d0806a0860b3e,
    EmptyIntList: [],
    IntList:
    [
        1,
        2,
        3
    ],
    StringList:
    [
        one,
        two,
        three
    ],
    StringIntMap:
    {
        a: 1,
        b: 2,
        c: 3
    }
}

If you don't feel like copying and pasting Chris S's code, the Visual Studio 2008 samples come with an ObjectDumper.

Drive:\Program Files\Microsoft Visual Studio 9.0\Samples\1033\LinqSamples\ObjectDumper

Here is an alternative:

using System.Reflection;
public void Print(object value)
{
    PropertyInfo[] myPropertyInfo;
    string temp="Properties of "+value+" are:\n";
    myPropertyInfo = value.GetType().GetProperties();
    for (int i = 0; i < myPropertyInfo.Length; i++)
    {
        temp+=myPropertyInfo[i].ToString().PadRight(50)+" = "+myPropertyInfo[i].GetValue(value, null)+"\n";
    }
    MessageBox.Show(temp);
}

(just touching level 1, no depth, but says a lot)

For most classes, you could use the DataContractSerializer

I just came across a similar requirement in a Blazor project, and came up with the following very simple component to output an object's (and it's child objects') data to the screen:

ObjectDumper.razor:

@using Microsoft.AspNetCore.Components
@using Newtonsoft.Json

  <div>
    <button onclick="@DumpVMToConsole">@ButtonText</button>
    <pre id="json">@_objectAsJson</pre>
  </div>


@functions {

  // This component allows the easy visualisation of the values currently held in 
  // an object and its child objects.  Add this component to a page and pass in a 
  // param for the object to monitor, then press the button to see the object's data
  // as nicely formatted JSON
  // Use like this:  <ObjectDumper ObjectToDump="@_billOfLadingVM" />

  [Parameter]
  private object ObjectToDump { get; set; }

  [Parameter]
  private string ButtonText { get; set; } = "Show object's data";

  string _buttonText;

  string _objectAsJson = "";

  public void DumpVMToConsole()
  {
    _objectAsJson = GetObjectAsFormattedJson(ObjectToDump);
    Console.WriteLine(_objectAsJson);
  }

  public string GetObjectAsFormattedJson(object obj)
  {
    return JsonConvert.SerializeObject(
      value: obj, 
      formatting: Formatting.Indented, 
      settings: new JsonSerializerSettings
      {
        PreserveReferencesHandling = PreserveReferencesHandling.Objects
      });
  }

}

You then stick that somewhere on a Blazor page as follows:

<ObjectDumper ObjectToDump="@YourObjectToVisualise" />

Which then renders a button you can press to see the current values of the bound object:

I've stuck that in a GitHub repo: tomRedox/BlazorObjectDumper

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!