11 Stimmen

Dynamische Überschreibung von ToString() mit Reflection

Im Allgemeinen überschreibe ich die Methode ToString(), um die Eigenschaftsnamen und die ihnen zugeordneten Werte auszugeben. Ich habe ein bisschen müde, diese von Hand zu schreiben, so dass ich für eine dynamische Lösung suchen.

Haupt:

TestingClass tc = new TestingClass()
{
    Prop1 = "blah1",
    Prop2 = "blah2"
};
Console.WriteLine(tc.ToString());
Console.ReadLine();

TestingClass:

public class TestingClass
{
    public string Prop1 { get; set; }//properties
    public string Prop2 { get; set; }
    public void Method1(string a) { }//method
    public TestingClass() { }//const
    public override string ToString()
    {
        StringBuilder sb = new StringBuilder();
        foreach (Type type in System.Reflection.Assembly.GetExecutingAssembly().GetTypes())
        {
            foreach (System.Reflection.PropertyInfo property in type.GetProperties())
            {
                sb.Append(property.Name);
                sb.Append(": ");
                sb.Append(this.GetType().GetProperty(property.Name).Name);
                sb.Append(System.Environment.NewLine);
            }
        }
        return sb.ToString();
    }
}

Diese gibt derzeit aus:

Prop1: System.String Prop1
Prop2: System.String Prop2

Gewünschter Output:

Prop1: blah1
Prop2: blah2

Ich bin offen für andere Lösungen, es muss nicht unbedingt eine Reflexion sein, es muss nur das gewünschte Ergebnis liefern.

20voto

Simon Woker Punkte 4914

Das funktioniert bei mir:

public class TestingClass
{
    public string Prop1 { get; set; }//properties
    public string Prop2 { get; set; }
    public void Method1(string a) { }//method
    public TestingClass() { }//const
    public override string ToString()
    {
        StringBuilder sb = new StringBuilder();
        foreach (System.Reflection.PropertyInfo property in this.GetType().GetProperties())
        {
            sb.Append(property.Name);
            sb.Append(": ");
            if (property.GetIndexParameters().Length > 0)
            {
                sb.Append("Indexed Property cannot be used");
            }
            else
            {
                sb.Append(property.GetValue(this, null));
            }

            sb.Append(System.Environment.NewLine);
        }

        return sb.ToString();
    }
}

Um sie überall verfügbar zu machen, können Sie eine Erweiterung erstellen.
Es ist nicht möglich, Methoden in einer Erweiterung zu überschreiben, aber es sollte Ihr Leben vereinfachen.

public static class MyExtensions
{
    public static string ToStringExtension(this object obj)
    {
        StringBuilder sb = new StringBuilder();
        foreach (System.Reflection.PropertyInfo property in obj.GetType().GetProperties())
        {

            sb.Append(property.Name);
            sb.Append(": ");
            if (property.GetIndexParameters().Length > 0)
            {
                sb.Append("Indexed Property cannot be used");
            }
            else
            {
                sb.Append(property.GetValue(obj, null));
            }

            sb.Append(System.Environment.NewLine);
        }

        return sb.ToString();
    }
}

Sie können dann aufrufen ToStringExtension() auf jedes Objekt.
Der Nachteil ist, dass es nicht perfekt für Listen usw. funktioniert:

var list = new List<string>();
// (filling list ommitted)
list.ToStringExtension();
// output:
// Capacity: 16
// Count: 11
// Item: Indexed Property cannot be used

5voto

ΩmegaMan Punkte 26232

Hier ist eine Erweiterung, die die Standardtypen wie string, int und Datetime, aber auch String-Listen ausgibt (unten in AccessPoints was die obige Antwort nicht berücksichtigen konnte). Beachten Sie, dass die Ausgabe wie folgt ausgerichtet ist:

Name         : Omegaman
ID           : 1
Role         : Admin
AccessPoints : Alpha, Beta, Gamma
WeekDays     : Mon, Tue
StartDate    : 3/18/2014 12:16:07 PM

Nachfolgend die Erweiterung, die jeden Typ aufnimmt, solange es sich um eine Klasse handelt. Sie reflektiert dann die öffentlichen und privaten Eigenschaften und meldet sie, wenn sie nicht null sind.

public static string ReportAllProperties<T>(this T instance) where T : class
{

    if (instance == null)
        return string.Empty;

    var strListType = typeof(List<string>);
    var strArrType  = typeof(string[]);

    var arrayTypes   = new[] { strListType, strArrType };
    var handledTypes = new[] { typeof(Int32), typeof(String), typeof(bool), typeof(DateTime), typeof(double), typeof(decimal), strListType, strArrType };

    var validProperties = instance.GetType()
                                  .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                                  .Where(prop => handledTypes.Contains(prop.PropertyType))
                                  .Where(prop => prop.GetValue(instance, null) != null)
                                  .ToList();

    var format = string.Format("{{0,-{0}}} : {{1}}", validProperties.Max(prp => prp.Name.Length));

    return string.Join(
             Environment.NewLine,
             validProperties.Select(prop => string.Format(format, 
                                                          prop.Name,
                                                          (arrayTypes.Contains(prop.PropertyType) ? string.Join(", ", (IEnumerable<string>)prop.GetValue(instance, null))
                                                                                                  : prop.GetValue(instance, null)))));
}

Verwendung

myInstance.ReportAllProperties()

Beachten Sie, dass dies auf meinem Blog-Artikel basiert C#: ToString, um alle Eigenschaften, auch private, über Reflection zu melden die eine fundiertere Erklärung der Vorgänge liefert.

1voto

jiri Punkte 11

Ich würde JSON verwenden, Serializer wird die ganze harte Arbeit für Sie tun:

    public static class ObjectExtensions
    {
        public static string ToStringEx(this object obj)
        {
            return JsonSerializer.Serialize(obj, new JsonSerializerOptions { WriteIndented = true });
        }
    }

0voto

Eyal Punkte 21

Ich habe Folgendes gefunden, das mit den meisten komplizierten Typen (einschließlich List) funktioniert:

public static string ToXml(object Obj, System.Type ObjType)
{
    try
    {
        XmlSerializer ser;
        XmlSerializerNamespaces SerializeObject = new mlSerializerNamespaces();
        ser = new XmlSerializer((ObjType));
        MemoryStream memStream;
        memStream = new MemoryStream();
        XmlTextWriter xmlWriter;
        xmlWriter = new XmlTextWriter(memStream, Encoding.UTF8);
        xmlWriter.Namespaces = true;
        XmlQualifiedName[] qualiArrayXML = SerializeObject.ToArray();
        ser.Serialize(xmlWriter, Obj);
        xmlWriter.Close();
        memStream.Close();
        string xml;
        xml = Encoding.UTF8.GetString(memStream.GetBuffer());
        xml = xml.Substring(xml.IndexOf(Convert.ToChar(60)));
        xml = xml.Substring(0, (xml.LastIndexOf(Convert.ToChar(62)) + 1));
        return xml;
    }
    catch (Exception ex)
    { return string.Empty; }
}

Verwendung:

string classAasString = ClassToXml.ToXml(a, typeof(ClassA)); //whare ClassA is an object

0voto

Johannes Punkte 6009

Ich bin selbst auf dieses Problem gestoßen, als ich nach einer Möglichkeit suchte, die Daten in etwas Lesbares zu serialisieren. Wenn es keine schreibgeschützten Eigenschaften gibt, kann die Xml-Serialisierung eine lesbare Zeichenfolge liefern. Wenn es jedoch nur lesbare Eigenschaften/Felder gibt, ist die Xml-Serialisierung keine Option.

    public static string ToString(object serializeable)
    {
        var type = serializeable.GetType();
        try
        {
            var sw = new StringWriter();
            new XmlSerializer(type).Serialize(sw, serializeable);
            return sw.ToString();
        }
        catch
        {
            return type.FullName;
        }
    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X