Относительно легко создать функцию лямбды, которая возвратит значение свойства от объекта, даже включая глубокие свойства...
Func<Category, string> getCategoryName = new Func<Category, string>(c => c.Name);
и это можно назвать следующим образом...
string categoryName = getCategoryName(this.category);
Но, учитывая только получающуюся функцию выше (или выражение первоначально раньше создавал функцию), может кто-либо обеспечивать простой способ создать противостоящее действие...
Action<Category, string> setCategoryName = new Action<Category, string>((c, s) => c.Name = s);
... это позволит тому же значению свойства быть установленным следующим образом?
setCategoryName(this.category, "");
Обратите внимание, что я ищу способ создать действие программно из функции или выражения - я надеюсь, что показал, что я уже знаю, как создать его вручную.
Я открыт для ответов, которые работают и в .net 3.5 и в 4.0.
Спасибо.
ОБНОВЛЕНИЕ:
Возможно, я не ясен в своем вопросе, таким образом позвольте мне попытаться продемонстрировать более ясно, что я пытаюсь сделать.
У меня есть следующий метод (что я создал в целях этого вопроса)...
void DoLambdaStuff<TObject, TValue>(TObject obj, Expression<Func<TObject, TValue>> expression) {
Func<TObject, TValue> getValue = expression.Compile();
TValue stuff = getValue(obj);
Expression<Action<TObject, TValue>> assignmentExpression = (o, v) => Expression<TObject>.Assign(expression, Expression.Constant(v, typeof(TValue)));
Action<TObject, TValue> setValue = assignmentExpression.Compile();
setValue(obj, stuff);
}
То, что я ищу, - то, как я создаю "assignmentExpression" в рамках кода так, чтобы я мог скомпилировать его в setValue? Я полагаю, что это связано с Выражением. Присвойтесь, но я просто не могу разработать корректную комбинацию параметров для завершения кода.
Возможный результат должен смочь звонить
Category category = *<get object from somewhere>*;
this.DoLambdaStuff(category, c => c.Name);
и это в свою очередь создаст метод считывания и метод set для свойства "Name" объекта Категории.
Версия выше компиляций, но когда я называю setValue () он приводит к ArgumentException с "Выражением, должно быть записываемым".
Еще раз спасибо.
Это должно быть возможно с использованием деревьев выражений , которые могут быть созданы из лямбда-выражений, изменены и затем скомпилированы в делегат.
Хорошо, код, который я ищу, выглядит примерно так ...
ParameterExpression objectParameterExpression = Expression.Parameter(
typeof(TObject)),
valueParameterExpression = Expression.Parameter(typeof(TValue)
);
Expression<Action<TObject, TValue>> setValueExpression = Expression.Lambda<Action<TObject, TValue>>(
Expression.Block(
Expression.Assign(
Expression.Property(
objectParameterExpression,
((MemberExpression) expression.Body).Member.Name
),
valueParameterExpression
)
),
objectParameterExpression,
valueParameterExpression
);
Action<TObject, TValue> setValue = setValueExpression.Compile();
Этот код работает, но только для поверхностных свойств (то есть свойств непосредственного объекта), но не работает для глубоких свойств - хотя Функция getter может работать для глубоких свойств. Было бы интересно узнать, может ли кто-нибудь помочь мне изменить это для работы с глубокими свойствами, но я подниму это как отдельный вопрос.