Другим решением является использование ExpressionVisitor
заменить параметр в правом выражении со всем левым выражением, другими словами, вставлять левые один в правой.
Expression visitor будет довольно простым, добавьте необходимые данные в конструктор, переопределите один метод и все.
internal sealed class ParameterReplaceVisitor : ExpressionVisitor
{
private readonly ParameterExpression _searched;
private readonly Expression _replaced;
public ParameterReplaceVisitor(ParameterExpression searched, Expression replaced)
{
if (searched == null)
throw new ArgumentNullException(nameof(searched));
if (replaced == null)
throw new ArgumentNullException(nameof(replaced));
_searched = searched;
_replaced = replaced;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == _searched)
return _replaced;
return base.VisitParameter(node);
}
}
Его можно довольно легко расширить, чтобы обрабатывать коллекции выражений в конструкторе, но я сохранил его.
Теперь вам просто нужно использовать его на телах выражений и построить новую лямбду.
private static Expression<Func<TIn, TOut>> Merge<TIn, TInter, TOut>(Expression<Func<TIn, TInter>> left, Expression<Func<TInter, TOut>> right)
{
var merged = new ParameterReplaceVisitor(right.Parameters[0], left.Body).Visit(right.Body);
var lambda = Expression.Lambda<Func<TIn, TOut>>(merged, left.Parameters[0]);
return lambda;
}
Я тестировал его на этот код:
Expression<Func<string, int>> l = s => s.Length + 5;
Expression<Func<int, string>> r = i => i.ToString() + " something";
var merged = Merge(l, r);
var res = merged.Compile()("test");
и результат, как и ожидалось: 9 something
.
EDIT: Если вы беспокоитесь, почему вы используете выражения вместо простых Func
? Тогда вы можете просто вызвать один за другим. Анализируются ли деревья выражений?
Спасибо! Как я могу это оптимизировать? производительность имеет решающее значение в этом конкретном случае. –
Я изменил ответ – LmTinyToon
Второе предложенное решение создает делегаты и анонимные объекты, которые, я бы сказал, не очень хороши с точки зрения производительности .. или я чего-то не хватает? –