Durchlaufen Sie einen Linq-Ausdruck, um den Wert eines Eigenschaftsfelds festzulegen

c# expression-trees linq

Frage

Dies ist eine sehr komplizierte Frage, obwohl sie einfach aussieht. Ich denke, ich müsste den gesamten Ausdrucksbaum durchqueren, wenn nicht jemand einen besseren Weg kennt.

Sagen wir, ich habe ein Benutzerobjekt

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

Wie kann ich linq-Ausdrücke verwenden, um die Eigenschaft von Name festzulegen

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

Akzeptierte Antwort

Nun, Sie müssten nicht nur den Ausdrucksbaum durchqueren, sondern Sie müssten auch die letzte Eigenschaft "Getter", die Sie treffen, in einen "Setter" der Eigenschaft konvertieren. Im Wesentlichen möchten Sie den Ausdruck finden, der als "Ziel" des Getters fungiert (dh das Objekt, von dem die Eigenschaft erhalten wird), ihn auswerten, um das Ziel zu erhalten, dann den entsprechenden Setter für die endgültige Eigenschaft finden und nenne es mit dem Ziel und dem neuen Wert.

Beachten Sie, dass Sie dadurch, dass Sie nur die Ausdrucksbaumstruktur benötigen, um den "Getter" darzustellen, einen Teil der Sicherheit bei der Kompilierungszeit verlieren, die Sie vielleicht erwarten ... weil ein Aufrufer eine schreibgeschützte Eigenschaft übergeben könnte:

SetValue(c => c.Account.Name.Length, 0); // string.Length is read-only

Eine andere Alternative wäre, den Code so zu ändern, dass der Lambda-Ausdruck stattdessen den Setter darstellt:

SetValue(c => c.Account.Name.Length, 0); // string.Length is read-only

Dann brauchen Sie nicht einmal einen Ausdrucksbaum - Sie könnten einen einfachen Delegaten verwenden und ihn nur entsprechend ausführen.

Leider haben Sie uns nicht genügend Informationen darüber gegeben, was Sie erreichen möchten, um zu wissen, ob dies ein praktikabler Vorschlag ist.


Beliebte Antwort

Ja, Sie müssen den gesamten Ausdrucksbaum durchqueren, was für Sie eine Herausforderung darstellt, wenn Sie im allgemeinen Fall arbeiten wollen. Kannst du das nicht einfach tun?

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

Wo SetValue wie folgt definiert ist:

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

Oder ohne den generischen Parameter, wenn dies nur mit User funktioniert.




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