2 votes

Traverser une expression Linq pour définir la valeur d'un champ de propriété

C'est une question très compliquée même si elle semble simple. Je pense que je devrais traverser tout l'arbre d'expression à moins que quelqu'un connaisse une meilleure façon.

Disons que j'ai un objet utilisateur

class User
{
    public UserAccount Account {get;set;}
}
class UserAccount
{
    public Name {get;set;}
}
var user = new User() { Account = new UserAccount()};

Comment pourrais-je utiliser des expressions linq pour définir la propriété de Name

SetValue(c => c.Account.Name, "Test");

2voto

Jon Skeet Points 692016

Eh bien, non seulement vous auriez à parcourir l'arbre d'expression : vous auriez également à convertir la propriété finale "getter" que vous rencontrez en un "setter" de propriété. Fondamentalement, vous voudriez trouver l'expression qui agit comme la "cible" du getter (c'est-à-dire l'objet dont il va obtenir la propriété), l'évaluer pour obtenir la cible, puis trouver le setter correspondant pour la propriété finale, et l'appeler avec la cible et la nouvelle valeur.

Notez que en ne nécessitant que l'arbre d'expression pour représenter le "getter", vous perdez une partie de la sécurité à la compilation à laquelle vous pourriez vous attendre... parce qu'un appelant pourrait passer une propriété en lecture seule :

SetValue(c => c.Account.Name.Length, 0); // string.Length est en lecture seule

Une autre alternative serait de modifier votre code pour que l'expression lambda représente le setter au lieu du getter :

SetValue((c, value) => c.Account.Name = value, "Test");

Alors vous n'auriez même pas besoin d'un arbre d'expression - vous pourriez utiliser un simple délégué, et l'exécuter de manière appropriée.

Malheureusement, vous ne nous avez pas vraiment donné suffisamment d'informations sur ce que vous essayez de réaliser pour savoir si c'est une suggestion réalisable.

1voto

Darin Dimitrov Points 528142

Oui, vous devrez parcourir tout l'arbre d'expression, ce qui pourrait être difficile si vous voulez travailler dans le cas général. Ne pouvez-vous pas simplement faire ceci à la place :

SetValue(c => c.Account.Name = "Test");

SetValue est défini comme ceci :

public void SetValue(Action action)
{
    ...
}

Ou sans le paramètre générique si cela fonctionne seulement avec User.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X