Utilisation d'un arbre d'expression pour lire le nom et la valeur d'une propriété. Y a-t-il une alternative?

c# expression-trees

Question

Hypothèses

Supposons que j'ai une classe avec une propriété:

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

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

Et supposons maintenant que j'ai créé une instance de cette classe:

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

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

Ce que je veux

Je veux que ceci soit imprimé sur la console:

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

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

Part de gâteau! J'utilise ce code pour produire la sortie souhaitée:

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

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

Problème

Je viole DRY, parce que "Prop" apparaît deux fois dans le code ci-dessus. Si je refacture la classe et modifie le nom de la propriété, je dois également modifier le littéral de chaîne. Il y a aussi beaucoup de code passe-partout, si j'avais une classe avec beaucoup de propriétés.

Solution proposée

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

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

Où la méthode buildString ressemble à ceci:

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

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

Question

La solution ci-dessus fonctionne bien et j'en suis heureuse, mais s'il existe un moyen plus simple et moins "effrayant" de résoudre ce problème, cela me rendrait beaucoup plus heureux. Existe-t-il une alternative plus facile pour obtenir le même résultat avec moins de code et plus simple? Peut-être quelque chose sans arbres d'expression?

modifier

Basé sur la bonne idée de Manu (voir ci-dessous), je pourrais utiliser cette méthode d'extension:

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

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

C'est excellent pour obtenir une représentation sous forme de chaîne pour toutes les propriétés d'une instance.

Mais: à partir de cette énumération, comment pourrais-je choisir en toute sécurité une propriété spécifique? De nouveau, j'utiliserais des arbres d'expression ... ou est-ce que je ne vois pas le bois pour les arbres?

Modifier 2

L'utilisation d'arbres de réflexion ou d'expression est une question de goût.

L'idée de Luke d'utiliser des initialiseurs de projection est tout simplement géniale. A partir de sa réponse, j'ai finalement construit cette méthode d'extension (qui est fondamentalement une version LINQ'd de sa réponse):

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

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

Maintenant, un appel ressemblera à ceci:

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

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

Ce qui est un peu plus joli que l'appel initial avec un lambda (mais c'est aussi une question de goût, je suppose). La suggestion de Luke est toutefois supérieure à ma solution, car elle permet de spécifier autant de propriétés que vous le souhaitez (voir ci-dessous).

Réponse acceptée

Vous pouvez passer un type anonyme à une méthode BuildStrings , en tirant parti des initialiseurs de projection pour créer automatiquement les noms et les valeurs des propriétés du type anonyme. Dans la méthode, vous utiliseriez la réflexion pour interroger ces propriétés.

Cela vous permettrait également de transmettre plusieurs éléments si vous le souhaitez. Vous pouvez également passer des champs et des locales ainsi que des propriétés, car ils seraient tous projetés en tant que propriétés de type anonyme pouvant ensuite être interrogées avec GetProperties etc. l'objet qui est passé. Vous pouvez passer n'importe quel type.)

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)));
}

Réponse d'expert

J'ai vu cela se faire avec un délégué et un interrogatoire IL , mais ce n'est pas exactement plus simple. En bref, non: il n'y a pas d' infoof sur C #. Voici ce qu'en pense Eric Lippert: In Foof We Trust: A Dialogue




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi