Правильный Способ Преобразования Выражения> В Другое Выражение>
У меня есть два выражения.
У меня есть вход предиката типа Expression<Func<Foo, bool>>
Я хотел бы преобразовать исходное выражение В Тип Expression<Func<Bar, bool>>
Какова была бы логика, чтобы сделать это?
Я пытался использовать Expression.Convert()
, но я считаю, что делаю это неправильно.
1 ответ:
Для преобразования
То, что вы делаете, - это просто составление выражений. Составление выражений несколько сложнее, чем составление функций, где один может просто вызвать другой, передавая его результат в качестве параметра. Здесь мы должны заменить все экземпляры параметра второй функции телом первой:Expression<Func<Foo, bool>>
вExpression<Func<Bar, bool>>
Вам также понадобитсяExpression<Func<Bar, Foo>>
, чтобы обработать преобразование.public static Expression<Func<TFirstParam, TResult>> Compose<TFirstParam, TIntermediate, TResult>( this Expression<Func<TFirstParam, TIntermediate>> first, Expression<Func<TIntermediate, TResult>> second) { var param = Expression.Parameter(typeof(TFirstParam), "param"); var newFirst = first.Body.Replace(first.Parameters[0], param); var newSecond = second.Body.Replace(second.Parameters[0], newFirst); return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param); }
Это опирается на следующий метод, чтобы замените все экземпляры одного выражения другим:
public static Expression Replace(this Expression expression, Expression searchEx, Expression replaceEx) { return new ReplaceVisitor(searchEx, replaceEx).Visit(expression); } internal class ReplaceVisitor : ExpressionVisitor { private readonly Expression from, to; public ReplaceVisitor(Expression from, Expression to) { this.from = from; this.to = to; } public override Expression Visit(Expression node) { return node == from ? to : base.Visit(node); } }
Теперь мы можем сделать следующее:
Expression<Func<Foo, bool>> predicate = GetPrediate(); Expression<Func<Bar, Foo>> selector = GetSelector(); Expression<Func<Bar, bool>> newPredicate = selector.Compose(predicate);