Dav*_*vid 2 .net linq expression-trees
如何制作通用的辅助方法,以将Func使用的类型从表达式中的一种类型转换为另一种类型
我有一个Expression<Func<IEmployee, bool>>,我想将其转换为
Expression<Func<Employee, bool>>.
Run Code Online (Sandbox Code Playgroud)
第二个类型始终实现第一个类型。一个通用的解决方案是我要实现的目标。
编辑
我已对问题进行了更清晰的编辑。
好吧,您可以创建一个表达式,该表达式将强制转换并将其参数转发给原始表达式:
Expression<Func<IEmployee, bool>> source = ...
var param = Expression.Parameter(typeof(Employee));
// Types the argument as the type expected by the source expression
// and then forwards it...
var invocationExpr = Expression.Invoke
(source, Expression.TypeAs(param, typeof(IEmployee)));
var result = Expression.Lambda<Func<Employee, bool>>(invocationExpr, param);
Run Code Online (Sandbox Code Playgroud)
如果提供程序不支持调用表达式,则可能需要一个更复杂的解决方案来替换源表达式中的Parameters。
编辑:好的,因为您说您的提供者不喜欢结果表达式,所以这里是替代示例。这实际上是参数替换器的外观的粗略显示(我现在只是作为示例编写),但是它可以很好地满足您的目的。
public static class ParameterReplacer
{
// Produces an expression identical to 'expression'
// except with 'source' parameter replaced with 'target' parameter.
public static Expression<TOutput> Replace<TInput, TOutput>
(Expression<TInput> expression,
ParameterExpression source,
ParameterExpression target)
{
return new ParameterReplacerVisitor<TOutput>(source, target)
.VisitAndConvert(expression);
}
private class ParameterReplacerVisitor<TOutput> : ExpressionVisitor
{
private ParameterExpression _source;
private ParameterExpression _target;
public ParameterReplacerVisitor
(ParameterExpression source, ParameterExpression target)
{
_source = source;
_target = target;
}
internal Expression<TOutput> VisitAndConvert<T>(Expression<T> root)
{
return (Expression<TOutput>)VisitLambda(root);
}
protected override Expression VisitLambda<T>(Expression<T> node)
{
// Leave all parameters alone except the one we want to replace.
var parameters = node.Parameters.Select
(p => p == _source ? _target : p);
return Expression.Lambda<TOutput>(Visit(node.Body), parameters);
}
protected override Expression VisitParameter(ParameterExpression node)
{
// Replace the source with the target, visit other params as usual.
return node == _source ? _target : base.VisitParameter(node);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后将其用作:
Expression<Func<IEmployee, bool>> expression = ...
var result = ParameterReplacer.Replace
<Func<IEmployee, bool>, Func<Employee, bool>>
(expression,
expression.Parameters.Single(),
Expression.Parameter(typeof(Employee));
Run Code Online (Sandbox Code Playgroud)