Создайте действие лямбды из выражения function

Относительно легко создать функцию лямбды, которая возвратит значение свойства от объекта, даже включая глубокие свойства...

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 с "Выражением, должно быть записываемым".

Еще раз спасибо.

7
задан Martin Robins 15 May 2010 в 18:17
поделиться

2 ответа

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

0
ответ дан 7 December 2019 в 01:17
поделиться

Хорошо, код, который я ищу, выглядит примерно так ...

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 может работать для глубоких свойств. Было бы интересно узнать, может ли кто-нибудь помочь мне изменить это для работы с глубокими свойствами, но я подниму это как отдельный вопрос.

3
ответ дан 7 December 2019 в 01:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: