따라서 런타임에 현재 객체의 상태를 보려면 Visual Studio Immediate 창이 제공하는 것이 정말 좋습니다. 간단하게
? objectname
객체의 멋진 '덤프'를 나에게 줄 것입니다.
코드 에서이 작업을 수행하는 쉬운 방법이 있습니까? 그래서 로깅 할 때 비슷한 작업을 수행 할 수 있습니까?
따라서 런타임에 현재 객체의 상태를 보려면 Visual Studio Immediate 창이 제공하는 것이 정말 좋습니다. 간단하게
? objectname
객체의 멋진 '덤프'를 나에게 줄 것입니다.
코드 에서이 작업을 수행하는 쉬운 방법이 있습니까? 그래서 로깅 할 때 비슷한 작업을 수행 할 수 있습니까?
답변:
w3wp.exe
내가 ObjectDumper
같은 것을 사용하려고 할 때 충돌Request.DumpToString("aaa");
더 큰 객체 그래프의 경우 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);
look Locals
앞에 $ 가 붙은 창 에 자동으로 표시 되거나 시계를 추가 할 수 있습니다. Value
인스펙터 에서 컬럼 의 오른쪽 에는 드롭 다운 캐럿이있는 돋보기가 옆에 있습니다. 드롭 다운 캐럿을 선택하고 Json Visualizer를 선택하십시오.
Visual Studio 2013을 사용하고 있습니다.
Newtonsoft.Json.JsonConvert.SerializeObject(sampleData, Formatting.Indented)
나는 이것을하는 더 좋은 방법이 있다고 확신하지만, 과거에는 객체를 내가 기록 할 수있는 문자열로 직렬화하기 위해 다음과 같은 방법을 사용했다.
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;
}
메소드가 직렬화 된 오브젝트가 아니라 예외를 리턴 할 수도 있으므로 로그하려는 오브젝트가 직렬화 가능한지 확인해야합니다.
Failed to access type 'System.__ComObject' failed
. 멍청한 놈, 도움을 주셔서 감사합니다.
Visual Studio Immediate Window를 사용할 수 있습니다
이것을 붙여 넣으십시오 ( actual
명명하게 객체 이름으로 변경 하십시오).
Newtonsoft.Json.JsonConvert.SerializeObject(actual);
JSON으로 객체를 인쇄해야합니다.
textmechanic 텍스트 도구 또는 notepad ++를 통해 복사하고 이스케이프 된 따옴표 ( \"
)와 "
개행 ( \r\n
)을 빈 공간으로 바꾼 다음 큰 따옴표 ( "
)를 시작과 끝에서 제거 하고 더 읽기 쉽게 jsbeautifier 에 붙여 넣으십시오 .
OP의 의견에 업데이트
public static class Dumper
{
public static void Dump(this object obj)
{
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(obj)); // your logger
}
}
그러면 객체를 덤프 할 수 있습니다.
이것이 시간을 절약하기를 바랍니다.
Console.Log(Newtonsoft.Json.JsonConvert.SerializeObject(actual));
? :) 그리고 그렇습니다 나는 그것을 정말로 놓쳤다. 이 질문은 google.co.uk/…
ServiceStack.Text 에는 정확하게 이것을 수행 하는 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
}
}
He didn't say fields
-그는 entire objects
필드를 포함 하여 말했다 . 그는 또한 Visual Studio의 직접 실행 창 기능을 달성하고자하는 것의 예로 언급했습니다 ( "단순한 작업만으로도 ? objectname
개체의 '덤프'형식을 지정할 수 있습니다" ). ? objectname
모든 필드를 인쇄합니다. This has been immensely helpful - one of my most used extension methods to date
-유용하다고 의심하지 않고 전체 객체를 덤프하는 것만 의심합니다.
Int32
필드에는 자체 MaxValue
필드가 Int32
있습니다 ...).하지만 좋은 지적이지만 객체와 확실히 전체 객체를 변경하지는 않습니다. -속성뿐만 아니라 필드로 구성됩니다. 무엇보다, (하나 그 주소하지 않았다) ? objectname
에서 Immediate Window
않는 무한 루프를 트리거하지 않고 - 디스플레이 분야. 그것이 나의 공감에 관한 것이라면, 나는 그것을 철회 할 수 있습니다 (잠금을 해제하여 알려 주면, 즉). 어쨌든 원칙적으로 동의하지 않습니다.
다음은 깔끔한 형식의 평면 객체를 작성하는 어리석은 간단한 방법입니다.
using Newtonsoft.Json.Linq;
Debug.WriteLine("The object is " + JObject.FromObject(theObjectToDump).ToString());
계속해서 객체는 먼저로 내부 JSON 표현으로 JObject.FromObject
변환 된 다음로로 JSON 문자열로 변환됩니다 ToString
. (물론 JSON 문자열은 간단한 객체를 아주 잘 표현한 것입니다. 특히 줄 ToString
바꿈과 들여 쓰기가 포함되어 있기 때문 입니다.) "ToString"은 물론 ( +
문자열과 객체를 연결하기 위해을 사용하여 암시되기 때문에) 외부 적입니다. 여기에 지정하고 싶습니다.
객체 및 컬렉션을 문자열 (및 기타)로 쉽게 덤프 할 수있는 ObjectPrinter 라는 라이브러리를 발견 했습니다. 내가 필요한 것을 정확하게 수행합니다.
다음은 동일한 작업을 수행하고 중첩 속성을 처리하는 다른 버전으로, 더 간단하다고 생각합니다 (외부 라이브러리에 대한 종속성이 없으며 로깅 이외의 작업을 수행하기 위해 쉽게 수정할 수 있음).
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"));
}
}
Date
당신의 내면의 물건에 재산 을 가지고 있다면 이것은 끔찍하게 죽을 것입니다 ... 그냥 ...
자신 만의 WriteLine 메서드를 작성할 수 있습니다.
public static void WriteLine<T>(T obj)
{
var t = typeof(T);
var props = t.GetProperties();
StringBuilder sb = new StringBuilder();
foreach (var item in props)
{
sb.Append($"{item.Name}:{item.GetValue(obj,null)}; ");
}
sb.AppendLine();
Console.WriteLine(sb.ToString());
}
다음과 같이 사용하십시오.
WriteLine(myObject);
컬렉션을 작성하려면
var ifaces = t.GetInterfaces();
if (ifaces.Any(o => o.Name.StartsWith("ICollection")))
{
dynamic lst = t.GetMethod("GetEnumerator").Invoke(obj, null);
while (lst.MoveNext())
{
WriteLine(lst.Current);
}
}
방법은 다음과 같습니다.
public static void WriteLine<T>(T obj)
{
var t = typeof(T);
var ifaces = t.GetInterfaces();
if (ifaces.Any(o => o.Name.StartsWith("ICollection")))
{
dynamic lst = t.GetMethod("GetEnumerator").Invoke(obj, null);
while (lst.MoveNext())
{
WriteLine(lst.Current);
}
}
else if (t.GetProperties().Any())
{
var props = t.GetProperties();
StringBuilder sb = new StringBuilder();
foreach (var item in props)
{
sb.Append($"{item.Name}:{item.GetValue(obj, null)}; ");
}
sb.AppendLine();
Console.WriteLine(sb.ToString());
}
}
이런 방식으로 if, else if
인터페이스, 속성, 기본 유형 등 및 재귀를 사용 하고 확인 하면 (재귀 적 방법이므로) 객체 덤프를 달성 할 수 있지만 지루합니다. Microsoft LINQ Sample의 객체 덤프를 사용하면 시간이 절약됩니다.
@engineforce 답변을 기반으로 Xamarin 솔루션의 PCL 프로젝트에서 사용중인이 클래스를 만들었습니다.
/// <summary>
/// Based on: https://stackoverflow.com/a/42264037/6155481
/// </summary>
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)
{
var nestingSpaces = "".PadLeft(nestingLevel * 4);
if (obj == null)
{
_dumpBuilder.AppendFormat("{0}null\n", nestingSpaces);
}
else if (obj is string || obj.GetType().GetTypeInfo().IsPrimitive || obj.GetType().GetTypeInfo().IsEnum)
{
_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 (PropertyInfo descriptor in obj.GetType().GetRuntimeProperties())
{
string name = descriptor.Name;
object value = descriptor.GetValue(obj);
_dumpBuilder.AppendFormat("{0}{1} ({2})\n", nestingSpaces, name, value != null ? value.GetType().ToString() : "<null>");
// TODO: Prevent recursion due to circular reference
if (name == "Self" && HasBaseType(obj.GetType(), "NSObject"))
{
// In ObjC I need to break the recursion when I find the Self property
// otherwise it will be an infinite recursion
Console.WriteLine($"Found Self! {obj.GetType()}");
}
else
{
DumpObject(value, nestingLevel + 1);
}
}
}
}
bool HasBaseType(Type type, string baseTypeName)
{
if (type == null) return false;
string typeName = type.Name;
if (baseTypeName == typeName) return true;
return HasBaseType(type.GetTypeInfo().BaseType, baseTypeName);
}
bool ImplementsDictionary(Type t)
{
return t is IDictionary;
}
}
위의 모든 경로는 객체가 XML 또는 JSON으로 직렬화 가능하거나
자체 솔루션을 구현해야 한다고 가정합니다 .
그러나 결국 당신은 여전히 같은 문제를 해결해야 할 시점에 도달합니다.
또한 로그는 더 많은 정보를 원합니다.
이 모든 것을 해결하는 최상의 솔루션이 있습니다.
이 Nuget 패키지를 사용하십시오 : Desharp .
모두 - 모든 유형의 애플리케이션에 대한 웹 및 데스크톱 응용 프로그램 . Desharp Github 문서를
참조하십시오 . 그것은이 많은 구성 옵션을 .
어디서나 전화하세요 :
Desharp.Debug.Log(anyException);
Desharp.Debug.Log(anyCustomValueObject);
Desharp.Debug.Log(anyNonserializableObject);
Desharp.Debug.Log(anyFunc);
Desharp.Debug.Log(anyFunc, Desharp.Level.EMERGENCY); // you can store into different files
도움이 될 것입니다.