Verwenden eines Ausdrucksbaums zum Lesen des Namens und Werts einer Eigenschaft. Gibt es eine Alternative?

c# expression-trees

Frage

Annahmen

Angenommen, ich habe eine Klasse mit einer Eigenschaft:

class ClassWithProperty
{
    public string Prop { get; private set; }

    public ClassWithProperty(string prop)
    {
        this.Prop = prop;
    }
}

Und nun nehme ich an, ich habe eine Instanz dieser Klasse erstellt:

class ClassWithProperty
{
    public string Prop { get; private set; }

    public ClassWithProperty(string prop)
    {
        this.Prop = prop;
    }
}

Was ich möchte

Ich möchte dies auf der Konsole ausdrucken lassen:

class ClassWithProperty
{
    public string Prop { get; private set; }

    public ClassWithProperty(string prop)
    {
        this.Prop = prop;
    }
}

Stück Kuchen! Ich verwende diesen Code, um die gewünschte Ausgabe zu erzeugen:

class ClassWithProperty
{
    public string Prop { get; private set; }

    public ClassWithProperty(string prop)
    {
        this.Prop = prop;
    }
}

Problem

Ich verletze DRY, weil "Prop" zweimal im obigen Code erscheint. Wenn ich die Klasse umgestalte und den Namen der Eigenschaft ändere, muss ich auch das Stringliteral ändern. Es gibt auch eine Menge Code, wenn ich eine Klasse mit vielen Eigenschaften hätte.

Vorgeschlagene Lösung

class ClassWithProperty
{
    public string Prop { get; private set; }

    public ClassWithProperty(string prop)
    {
        this.Prop = prop;
    }
}

Wo die buildString-Methode folgendermaßen aussieht:

class ClassWithProperty
{
    public string Prop { get; private set; }

    public ClassWithProperty(string prop)
    {
        this.Prop = prop;
    }
}

Frage

Die obige Lösung funktioniert gut und ich bin glücklich damit, aber wenn es eine einfachere und weniger "gruselige" Art gibt, das zu lösen, würde mich das viel glücklicher machen. Gibt es eine einfachere Alternative, um das gleiche Ergebnis mit weniger und einfacherem Code zu erreichen? Vielleicht etwas ohne Ausdrucksbäume?

Bearbeiten

Basierend auf Manus guter Idee (siehe unten) könnte ich diese Erweiterungsmethode verwenden:

class ClassWithProperty
{
    public string Prop { get; private set; }

    public ClassWithProperty(string prop)
    {
        this.Prop = prop;
    }
}

Es ist großartig, eine String-Repräsentation für alle Eigenschaften einer Instanz zu erhalten.

Aber: Wie könnte ich aus dieser Aufzählung typsicher eine bestimmte Eigenschaft auswählen? Wieder würde ich Ausdrucksbäume benutzen ... oder sehe ich nicht das Holz für die Bäume?

Bearbeiten 2

Reflektions- oder Expressionsbäume zu verwenden, ist Geschmackssache.

Lukes Idee, Projektionsinitialisierer zu verwenden, ist einfach brillant. Aus seiner Antwort baue ich schließlich diese Erweiterungsmethode (die im Grunde nur eine LINQ-Version seiner Antwort ist):

class ClassWithProperty
{
    public string Prop { get; private set; }

    public ClassWithProperty(string prop)
    {
        this.Prop = prop;
    }
}

Jetzt wird ein Anruf wie folgt aussehen:

class ClassWithProperty
{
    public string Prop { get; private set; }

    public ClassWithProperty(string prop)
    {
        this.Prop = prop;
    }
}

Das sieht ein bisschen schöner aus als mein ursprünglicher Anruf mit einem Lambda (aber das ist auch Geschmackssache, denke ich). Lukes Vorschlag ist meiner Lösung jedoch überlegen, da es erlaubt, beliebig viele Eigenschaften anzugeben (siehe unten).

Akzeptierte Antwort

Sie könnten einen anonymen Typ an eine BuildStrings Methode übergeben, indem Sie die Vorteile der Projektionsinitialisierer nutzen, um automatisch die Namen und Werte der Eigenschaften des anonymen Typs zu erstellen. Innerhalb der Methode würden Sie Reflection verwenden, um diese Eigenschaften abzufragen.

Auf diese Weise können Sie auch mehrere Elemente übergeben, wenn Sie dies wünschen. Sie könnten auch Felder und Locals sowie Eigenschaften übergeben, da sie alle als Eigenschaften des anonymen Typs projiziert werden, die dann mit GetProperties usw. abgefragt werden GetProperties . Natürlich zählt alles, was die Methode tatsächlich tut, alle Eigenschaften von das übergebene Objekt. Sie können jeden Typ übergeben.)

string result = BuildStrings(new { test.Prop }).First();
Console.WriteLine(result);

// or

string foo = "Test";
int bar = 42;

string results = BuildStrings(new { foo, bar, test.Prop });
foreach (string r in results)
{
    Console.WriteLine(r);
}

// ...

public static IEnumerable<string> BuildStrings(object source)
{
    return source.GetType().GetProperties().Select(
        p => string.Format("{0} = '{1}'", p.Name, p.GetValue(source, null)));
}

Expertenantwort

Ich habe es mit einer Delegierten- und IL-Befragung gesehen , aber das ist nicht gerade einfacher. Kurz gesagt, nein: Es gibt keine infoof in C #. Hier ist Eric Lipperts Meinung : In Foof We Trust: A Dialogue




Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum