Каков наилучший способ выгрузки целых объектов в журнал в C #? - PullRequest
108 голосов
/ 11 декабря 2008

Так что для просмотра текущего состояния объекта во время выполнения мне действительно нравится то, что дает мне окно Visual Studio Immediate. Просто делаю простой

? objectname

Даст мне красиво отформатированный «дамп» объекта.

Есть ли простой способ сделать это в коде, чтобы я мог сделать что-то подобное при регистрации?

Ответы [ 12 ]

53 голосов
/ 11 декабря 2008

Вы можете основывать что-то на коде ObjectDumper, который поставляется с примерами Linq .
Также посмотрите ответ на этот связанный вопрос , чтобы получить образец.

44 голосов
/ 03 октября 2014

Для более крупного графа объектов я использую Json, но с несколько иной стратегией. Во-первых, у меня есть статический класс, который легко вызывать, и статический метод, который оборачивает преобразование Json (примечание: может сделать это методом расширения).

using Newtonsoft.Json;

public static class F
{
    public static string Dump(object obj)
    {
        return JsonConvert.SerializeObject(obj);
    }
}

Тогда в вашем Immediate Window,

var lookHere = F.Dump(myobj);

lookHere будет автоматически отображаться в окне Locals с предваряющим знаком $ или вы можете добавить к нему часы. Справа от колонки Value в инспекторе есть увеличительное стекло с раскрывающейся кареткой рядом с ним. Выберите раскрывающуюся каретку и выберите визуализатор Json.

Screenshot of Visual Studio 2013 Locals window

Я использую Visual Studio 2013.

25 голосов
/ 11 декабря 2008

Я уверен, что есть лучшие способы сделать это, но в прошлом я использовал метод, подобный следующему, чтобы сериализовать объект в строку, которую я могу записать:

  private string ObjectToXml(object output)
  {
     string objectAsXmlString;

     System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(output.GetType());
     using (System.IO.StringWriter sw = new System.IO.StringWriter())
     {
        try
        {
           xs.Serialize(sw, output);
           objectAsXmlString = sw.ToString();
        }
        catch (Exception ex)
        {
           objectAsXmlString = ex.ToString();
        }
     }

     return objectAsXmlString;
  }

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

17 голосов
/ 18 августа 2010

У меня есть метод расширения T.Dump () , который делает именно это, рекурсивно выводит все свойства любого типа в хороший читаемый формат.

Пример использования:

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
    }
}
16 голосов
/ 23 июня 2015

Вы можете использовать Visual Studio Immediate Window

Просто вставьте это (очевидно, замените actual на имя вашего объекта):

Newtonsoft.Json.JsonConvert.SerializeObject(actual);

Должен печатать объект в формате JSON enter image description here

Вы должны быть в состоянии скопировать его поверх текстового механического текстового инструмента или notepad ++ и заменить экранированные кавычки (\") на " и символы новой строки (\r\n) на пустые пробел, затем удалите двойные кавычки (") из начала и конца и вставьте его в jsbeautifier , чтобы сделать его более читабельным.

ОБНОВЛЕНИЕ комментария ОП

public static class Dumper
{
    public static void Dump(this object obj)
    {
        Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(obj)); // your logger
    }
}

это должно позволить вам сбросить любой объект.

Надеюсь, это сэкономит вам время.

13 голосов
/ 11 июня 2014

Вот тупо простой способ написать плоский объект, красиво отформатированный:

using Newtonsoft.Json.Linq;

Debug.WriteLine("The object is " + JObject.FromObject(theObjectToDump).ToString());

Что происходит, так это то, что объект сначала преобразуется во внутреннее представление JSON с помощью JObject.FromObject, а затем преобразуется в строку JSON с помощью ToString. (И, конечно, строка JSON является очень хорошим представлением простого объекта, тем более что ToString будет содержать символы новой строки и отступы.) «ToString», конечно, является посторонним (как это подразумевается при использовании + для объединения строки и объект), но мне бы хотелось указать это здесь.

4 голосов
/ 11 декабря 2008

Вы можете использовать отражение и перебрать все свойства объекта, затем получить их значения и сохранить их в журнале. Форматирование действительно тривиально (вы можете использовать \ t для отступа свойств объекта и его значений):

MyObject
    Property1 = value
    Property2 = value2
    OtherObject
       OtherProperty = value ...
3 голосов
/ 16 февраля 2017

Ниже приведена еще одна версия, которая делает то же самое (и обрабатывает вложенные свойства), которая, на мой взгляд, более проста (не зависит от внешних библиотек и может быть легко изменена для выполнения других операций, кроме ведения журнала):

public class ObjectDumper
{
    public static string Dump(object obj)
    {
        return new ObjectDumper().DumpObject(obj);
    }

    StringBuilder _dumpBuilder = new StringBuilder();

    string DumpObject(object obj)
    {
        DumpObject(obj, 0);
        return _dumpBuilder.ToString();
    }

    void DumpObject(object obj, int nestingLevel = 0)
    {
        var nestingSpaces = "".PadLeft(nestingLevel * 4);

        if (obj == null)
        {
            _dumpBuilder.AppendFormat("{0}null\n", nestingSpaces);
        }
        else if (obj is string || obj.GetType().IsPrimitive)
        {
            _dumpBuilder.AppendFormat("{0}{1}\n", nestingSpaces, obj);
        }
        else if (ImplementsDictionary(obj.GetType()))
        {
            using (var e = ((dynamic)obj).GetEnumerator())
            {
                var enumerator = (IEnumerator)e;
                while (enumerator.MoveNext())
                {
                    dynamic p = enumerator.Current;

                    var key = p.Key;
                    var value = p.Value;
                    _dumpBuilder.AppendFormat("{0}{1} ({2})\n", nestingSpaces, key, value != null ? value.GetType().ToString() : "<null>");
                    DumpObject(value, nestingLevel + 1);
                }
            }
        }
        else if (obj is IEnumerable)
        {
            foreach (dynamic p in obj as IEnumerable)
            {
                DumpObject(p, nestingLevel);
            }
        }
        else
        {
            foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(obj))
            {
                string name = descriptor.Name;
                object value = descriptor.GetValue(obj);

                _dumpBuilder.AppendFormat("{0}{1} ({2})\n", nestingSpaces, name, value != null ? value.GetType().ToString() : "<null>");
                DumpObject(value, nestingLevel + 1);
            }
        }
    }

    bool ImplementsDictionary(Type t)
    {
        return t.GetInterfaces().Any(i => i.Name.Contains("IDictionary"));
    }
}
3 голосов
/ 25 августа 2015

Я нашел библиотеку с именем ObjectPrinter , которая позволяет легко создавать дампы объектов и коллекций в строки (и многое другое). Это именно то, что мне нужно.

3 голосов
/ 11 декабря 2008

Что мне нравится делать, так это переопределение ToString (), так что я получаю более полезный вывод, кроме имени типа. Это удобно в отладчике, вы можете видеть информацию, которую вы хотите об объекте, без необходимости его расширения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...