2011-06-01 10 views
14

Para ayudar a depurar algún código en el que estoy trabajando, comencé a escribir un método para imprimir recursivamente los nombres y valores de las propiedades de un objeto. Sin embargo, la mayoría de los objetos contienen tipos anidados y me gustaría imprimir sus nombres y valores también, pero solo en los tipos que he definido.Cómo imprimir recursivamente los valores de las propiedades de un objeto usando la reflexión

He aquí un resumen de lo que tengo hasta ahora:

public void PrintProperties(object obj) 
{ 
    if (obj == null) 
     return; 

    Propertyinfo[] properties = obj.GetType().GetProperties(); 

    foreach (PropertyInfo property in properties) 
    { 
     if ([property is a type I have defined]) 
     { 
      PrintProperties([instance of property's type]); 
     } 
     else 
     { 
      Console.WriteLine("{0}: {1}", property.Name, property.GetValue(obj, null)); 
     } 
    } 

Las partes entre las llaves están donde no estoy seguro.

Cualquier ayuda será muy apreciada.

+0

posible duplicado de [C#: Impresión de todas las propiedades de un objeto] (http://stackoverflow.com/questions/852181/c-printing-all-properties- of-an-object) –

Respuesta

23

El código siguiente tiene un intento de eso. Para "tipo I he definido" elegí ver los tipos en el mismo ensamblaje que los del tipo cuyas propiedades se están imprimiendo, pero deberá actualizar la lógica si sus tipos están definidos en ensamblajes múltiples.

public void PrintProperties(object obj) 
{ 
    PrintProperties(obj, 0); 
} 
public void PrintProperties(object obj, int indent) 
{ 
    if (obj == null) return; 
    string indentString = new string(' ', indent); 
    Type objType = obj.GetType(); 
    PropertyInfo[] properties = objType.GetProperties(); 
    foreach (PropertyInfo property in properties) 
    { 
     object propValue = property.GetValue(obj, null); 
     if (property.PropertyType.Assembly == objType.Assembly && !property.PropertyType.IsEnum) 
     { 
      Console.WriteLine("{0}{1}:", indentString, property.Name); 
      PrintProperties(propValue, indent + 2); 
     } 
     else 
     { 
      Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue); 
     } 
    } 
} 
+4

Este código no detecta _cycles_. Si hay un ciclo presente, terminará arrojando una 'StackOverflowException'. –

+0

Cierto, algún tipo de lista "ya visitada" debería mantenerse si hubiera ciclos posibles en el dominio del problema. Gracias por mencionarlo. – carlosfigueira

+0

corrección de minutos - último parámetro en la última consola. WriteLine debe ser {2} no {1} – zam6ak

8

¿Hay algún motivo en particular por el que desee utilizar la reflexión? su lugar se puede utilizar JavaScriptSerializer así:

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); 
string json = serializer.Serialize(obj); 
Console.WriteLine(json); 

En él se incluirán de forma recursiva todas las propiedades en cadena, y lanzar una excepción en el caso si aparecerá referencia circular.

+0

Esto funciona bien para mí –

+0

esto funcionó muy bien para mí, y trabajando en un sitio web, en lugar de 'Console.WriteLine()' He utilizado 'div.InnerHtml =" "; 'y la salida en la consola de Chrome incluso se imprimirá bonita. (solo para fines de prueba, por supuesto) – Chad

1

Apalancamiento de Leonid's answer, el siguiente código es lo que utilicé para crear un volcado Json legible de cualquier objeto. Ignora el campo nulo y agrega sangría para una mejor visualización (especialmente bueno para objetos SOAP).

public static string SerializeToLogJson(this object obj) 
     { 
      try 
      { 
       var json = JsonConvert.SerializeObject(obj, 
        Newtonsoft.Json.Formatting.None, 
        new JsonSerializerSettings { 
         NullValueHandling = NullValueHandling.Ignore, 
         Formatting = Formatting.Indented 
        }); 
       return json; 
      } 
      catch (Exception e) 
      { 
       log.ErrorFormat(e.Message, e); 
       return "Cannot serialize: " + e.Message; 
      } 
     } 
0

Newtonsoft biblioteca proporciona funciones muy simples para serializar cualquier objeto para JSON. Esta es una solución mucho más simple.

Newtonsoft.Json.JsonConvert.SerializeObject(objToSerialize); 

por ejemplo:

dynamic obj = new { x = 1, y = 2, z = "abc" }; 
string json = JsonConvert.SerializeObject(obj); 
//'json' string value: {"x":1,"y":2,"z":"abc"} 
Cuestiones relacionadas