Пройдите через выражение Linq, чтобы установить значение поля свойства - PullRequest
2 голосов
/ 02 сентября 2010

Это очень сложный вопрос, хотя выглядит просто.Я думаю, что мне придется обходить все дерево выражений, если кто-то не знает лучшего способа.

Допустим, у меня есть пользовательский объект

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

Как я могу использовать выражения linq для установки свойстваимени

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

Ответы [ 2 ]

2 голосов
/ 02 сентября 2010

Ну, вам нужно не только пройти по дереву выражений: вам также нужно преобразовать конечное свойство getter, с которым вы столкнетесь, в свойство setter.По сути, вы хотите найти выражение, которое действует как «цель» метода получения (т. Е. Объекта, для которого он собирается получить свойство), оценить его, чтобы получить цель, затем найти соответствующий метод установки для конечного свойства ивызовите его с целевым значением и новым значением.

Обратите внимание, что, требуя только, чтобы дерево выражений представляло «получатель», вы теряете часть безопасности во время компиляции, которую вы можете ожидать ... потому чтовызывающая сторона может передать свойство только для чтения:

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

Другой вариант - изменить код так, чтобы вместо него лямбда-выражение представляло сеттер:

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

Тогда вы бы не сталидаже не нужно дерево выражений - вы можете использовать простой делегат и просто выполнить его соответствующим образом.

К сожалению, вы на самом деле не дали нам достаточно информации о том, чего вы пытаетесь достичь, чтобы узнать, является ли этовыполнимое предложение.

1 голос
/ 02 сентября 2010

Да, вам придется пройти по всему дереву выражений, которое, если вы хотите работать в общем случае, может быть сложным.Вы не можете просто сделать это вместо этого:

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

Где SetValue определяется следующим образом:

public void SetValue<T>(Action<T> action)
{
    ...
}

Или без универсального параметра, если это будет работать только с User.

...