代码之家  ›  专栏  ›  技术社区  ›  Chris S

对象转储程序类

  •  44
  • Chris S  · 技术社区  · 16 年前

    我正在寻找一个类,它可以输出一个对象及其所有叶值,格式如下:

    User
      - Name: Gordon
      - Age : 60
      - WorkAddress
         - Street: 10 Downing Street
         - Town: London
         - Country: UK
      - HomeAddresses[0]
        ...
      - HomeAddresses[1]
        ...
    

    public class User
    {
        public string Name { get;set; }
        public int Age { get;set; }
        public Address WorkAddress { get;set; }
        public List<Address> HomeAddresses { get;set; }
    }
    
    public class Address
    {
        public string Street { get;set; }
        public string Town { get;set; }
        public string Country { get;set; }
    }
    

    PropertyGrid控件的一种字符串表示形式,不必为每种类型实现大量设计器。

    PHP有一个实现这一点的东西,叫做 var_dump

    有人能给我指一下这样的东西吗?或者,写一个作为赏金。

    11 回复  |  直到 8 年前
        1
  •  55
  •   Chris S    11 年前

    sgmoore链接中发布的对象转储程序:

    //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年更新

    YAML也很好地实现了这一目的,这就是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);
        }
    
        2
  •  31
  •   Vdex    16 年前

    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()); 
    
        3
  •  14
  •   Luke Hammer    7 年前

    你可以找到 ObjectDumper project 在GitHub上。你也可以 add it 通过Visual Studio和NuGet软件包管理器。

        4
  •  12
  •   Dan Lugg mab    13 年前

    System.Web.ObjectInfo.Print ( )将实现这一点,很好地格式化为HTML。

    例如:

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

    ObjectInfo.Print(...)

        6
  •  9
  •   Nathan Pond    12 年前

    我知道这是一个老问题,但我想我会抛出一个对我有用的替代方案,我花了大约两分钟的时间。

    http://james.newtonking.com/json

    (或nuget版本) http://www.nuget.org/packages/newtonsoft.json/

    参考组件:

    using Newtonsoft.Json;
    

    将JSON字符串转储到日志:

    txtResult.Text = JsonConvert.SerializeObject(testObj);
    
        7
  •  7
  •   Jake Pearson    16 年前

    只要稍加思考,你就能很容易地写出来。有点像:

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

        8
  •  7
  •   mythz    15 年前

    我有一个 handy T.Dump() Extension method 这应该非常接近你想要的结果。作为一种扩展方法,它是非侵入性的,应该适用于所有POCO对象。

    示例用法

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

    示例输出

    {
        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
        }
    }
    
        9
  •  2
  •   AJ.    16 年前

    驱动器:\Program Files\Microsoft Visual Studio 9.0\Samples\1033\LinqSamples\ObjectDumper

        10
  •  2
  •   e-motiv    14 年前

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

    (只是触摸1级,没有深度,但说明了很多)

        11
  •  1
  •   Ohad Schneider    15 年前

    对于大多数类,您可以使用 DataContractSerializer

        12
  •  1
  •   tomRedox    7 年前

    我刚刚在Blazor项目中遇到了类似的需求,并提出了以下非常简单的组件,用于将对象(及其子对象)的数据输出到屏幕:

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

    然后将其粘贴在Blazor页面的某个位置,如下所示:

    <ObjectDumper ObjectToDump="@YourObjectToVisualise" />
    

    然后渲染一个按钮,您可以按该按钮查看绑定对象的当前值:

    enter image description here

    我在GitHub回购协议中提到: tomRedox/BlazorObjectDumper

    推荐文章