Склеить два lambda выражения в одну

294
11 октября 2017, 05:44

Цель: собрать две лямбды в одну целую.

var columnExpr = GenerateMemberExpression<Trio<int?, int?, int?>, int?>("First");
Expression<Func<GameModelRowViewModel, Trio<int?, int?, int?>>> func =
    vm => vm.ProbModelViewModels.First(x => x.Model.Name == probName).Model.ThridEvents[cfName];

Заранее какое свойство будет взято из класса ThridEvents неизвестно.

Метод GenerateMemberExpression взят отсюда.

Послесловие (читать необязательно):

Проблема в поверхностном понимании работы "дерева выражений". В источниках, которые изучил, используются простые примеры сборки дерева выражений. Быть может кто может взять на себя такую ответственность и сделать суперпупер мануал по ним?

Answer 1

Например, можно модифицировать GenerateMemberExpression, чтобы передавать в него ваше выражение. Получится как-то так:

// TSource -- тип выражения-параметра
// TModel -- тип выражения, из которого нужно взять нужное свойство по имени
// pp -- параметр
public static Expression<Func<TSource, T>> GenerateMemberExpression<TSource, TModel, T>(
    string propertyName,
    Expression source,
    ParameterExpression p)
{
    var propertyInfo = typeof(TModel).GetProperty(propertyName);
    Expression columnExpr = Expression.Property(source, propertyInfo);
    if (propertyInfo.PropertyType != typeof(T))
        columnExpr = Expression.Convert(columnExpr, typeof(T));
    return Expression.Lambda<Func<TSource, T>>(columnExpr, p);
}
static void Main(string[] args)
{
    Expression<Func<GameModelRowViewModel, Trio<int?, int?, int?>>> func =
        vm => new Trio<int?, int?, int?>() { First = 5 };
    var memberExpr =
        GenerateMemberExpression<GameModelRowViewModel,
                                 Trio<int?, int?, int?>,
                                 int?>
           ("First", func.Body, func.Parameters[0]);
    // проверка
    var m = memberExpr.Compile();
    var result = m(new GameModelRowViewModel()); // 5
}

Другой подход — через Expression.Invoke. Функцию GenerateMemberExpression можно оставить, как в вашем вопросе.

Expression<Func<GameModelRowViewModel, Trio<int?, int?, int?>>> func =
    vm => new Trio<int?, int?, int?>() { First = 5 };
var memberExpr = GenerateMemberExpression<Trio<int?, int?, int?>, int?>("First", func.Body);
var combined = Expression.Lambda<Func<GameModelRowViewModel, int?>>(
    Expression.Invoke(memberExpr, func.Body),
    func.Parameters);
// проверка
var m = combined.Compile();
var result = m(new GameModelRowViewModel()); // 5
READ ALSO
Как подключить текстовый список в код на c#?

Как подключить текстовый список в код на c#?

Необходимо подключить список к проекту в vs получать оттуда строку, удалить и переместить в конец файлаКакими методами и как это делать в целом?

207
Отправка POST на сервер

Отправка POST на сервер

Нужно отправить POST-запрос на сервер, который должен отправляться с ключом dataСделал так:

224
EPPlus: добавить новую колонку

EPPlus: добавить новую колонку

Подскажите, пожалуйста, как добавить новую пустую колонку на лист через EPPlus С#?

244
Вопрос по C# | Типа: Как такое делается? [требует правки]

Вопрос по C# | Типа: Как такое делается? [требует правки]

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

302