Je cherche une classe qui peut sortir un objet et toutes ses valeurs de feuille dans un format similaire à ceci:
User
- Name: Gordon
- Age : 60
- WorkAddress
- Street: 10 Downing Street
- Town: London
- Country: UK
- HomeAddresses[0]
...
- HomeAddresses[1]
...
(Ou un format plus clair). Cela équivaudrait à:
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; }
}
Une sorte de représentation sous forme de chaîne du contrôle PropertyGrid, sans avoir à implémenter un grand nombre de concepteurs pour chaque type.
PHP a quelque chose qui fait cela appelé var_dump . Je ne veux pas utiliser de montre, car c'est pour imprimer.
Quelqu'un pourrait-il m'indiquer quelque chose comme ça s'il existe? Ou, écrivez-en un pour une prime.
Le dumper d'objets posté dans le lien de 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("{ }");
}
}
}
YAML sert également très bien cet objectif, c'est ainsi que cela peut être fait avec 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);
}
Vous pouvez utiliser le sérialiseur JSON, qui devrait être facile à lire pour toute personne habituée à travailler avec 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());
Mise à jour 2019
Vous pouvez trouver le projet ObjectDumper sur GitHub. Vous pouvez également l'ajouter via Visual Studio via le gestionnaire de packages NuGet.
Si vous travaillez avec du balisage, System.Web.ObjectInfo.Print
( Pages Web ASP.NET 2 ) accomplira cela, bien formaté pour HTML.
Par exemple:
@ObjectInfo.Print(new {
Foo = "Hello",
Bar = "World",
Qux = new {
Number = 42,
},
})
Dans une page Web, produit:
Voici une extension de Visual Studio que j'ai écrite pour faire ceci:
https://visualstudiogallery.msdn.Microsoft.com/c6a21c68-f815-4895-999f-cd0885d8774f
en action:
Je sais que c'est une vieille question, mais j'ai pensé jeter une alternative qui a fonctionné pour moi, m'a pris environ deux minutes à faire.
Installez Newtonsoft Json.NET: http://james.newtonking.com/json
(ou version nuget) http://www.nuget.org/packages/newtonsoft.json/
Assemblage de référence:
using Newtonsoft.Json;
Vider la chaîne JSON pour se connecter:
txtResult.Text = JsonConvert.SerializeObject(testObj);
Vous pourriez écrire cela très facilement avec un peu de réflexion. Quelque chose comme:
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);
}
}
}
Vous pouvez rédiger les méthodes PrintArray et PrintProperty.
J'ai une méthode pratique T.Dump () Extension qui devrait être assez proche des résultats que vous recherchez. En tant que méthode d'extension, elle est non invasive et devrait fonctionner sur tous les objets POCO.
Exemple d'utilisation
var model = new TestModel();
Console.WriteLine(model.Dump());
Exemple de sortie
{
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
}
}
Si vous n'avez pas envie de copier et coller le code de Chris S, les exemples Visual Studio 2008 sont livrés avec un ObjectDumper.
Lecteur:\Program Files\Microsoft Visual Studio 9.0\Samples\1033\LinqSamples\ObjectDumper
Voici une 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);
}
(juste toucher le niveau 1, pas de profondeur, mais en dit long)
Pour la plupart des classes, vous pouvez utiliser DataContractSerializer
Je viens de rencontrer une exigence similaire dans un projet Blazor, et j'ai trouvé le composant très simple suivant pour sortir les données d'un objet (et ses objets enfants) à l'écran:
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
});
}
}
Vous collez ensuite cela quelque part sur une page Blazor comme suit:
<ObjectDumper ObjectToDump="@YourObjectToVisualise" />
Ce qui rend ensuite un bouton sur lequel vous pouvez appuyer pour voir les valeurs actuelles de l'objet lié:
Je l'ai coincé dans un dépôt GitHub: tomRedox/BlazorObjectDumper