2017-06-07 148 views
0

作为WPF应用程序我建立表达式树和产生谓词作为过滤器的一部分来使用。该代码看起来是这样的:使用lambda表达式参数到另一个表达式?

public Expression BuildExpression(Expression parameter, string value) 
{ 
    MethodInfo toStringMethod = new Func<Object, string>((a) => a.ToString()).Method; 
    Expression lhs = Expression.Call(parameter, toStringMethod); 
    ConstantExpression rhs = Expression.Constant(value); 
    BinaryExpression result = Expression.Equal(lhs, rhs); 
    return result; 
} 

这是因为该参数是未知类型的表达式 - 这可能是一个整数,字符串,GUID或其他任何东西。问题在于没有丰富的评论很难理解这里发生的事情。我真的很想在这里使用一个拉姆达:

return parameter => parameter.ToString() == value; 

的问题是,因为预期这不起作用 - 产生的代表将在表达式调用toString(),而不是表达的价值。如果有帮助,参数是MemberExpression。

+0

一种可能性我之前没考虑 - 我想我可以用一个ExpressionVisitor(见https://stackoverflow.com/questions/457316/combining-two-expressions-expressionfunct-bool),使这项工作。 '表达<谓词>表达式1 = A => a.ToString()==值; 返回(新ReplaceExpressionVisitor(expr1.Parameters [0],参数))访问(表达式1);' – Mythgarr

回答

0

我能找到一种方法,用很少的额外的代码来做到这一点。此解决方案的主要灵感来自Mark Gravell的回答Combining two expressions (Expression<Func<T, bool>>)

从.net 4.0开始。还有就是ExpressionVistor类 允许你建立是EF安全表达式。

Expression<TDelegate>从LambdaExpression派生(如果你有兴趣了解更多关于如何将这些实际工作我建议你检查出的“LINQ - 表达式树可视化”的样品,目前位于https://code.msdn.microsoft.com/LINQ-Expression-Tree-47608cb5)。这行代码:

Expression<Predicate<Object>> e1 = a => a.ToString() == "foo"; 

创建具有单个ParameterExpression一个LambdaExpression(类型:对象,返回类型:布尔,身体:(LogicalBinaryExpression))。使用自定义ExpressionVisitor我们可以通过修改拉姆达的身体创造相同的结果,我以前的代码:

public class ReplaceExpressionVisitor 
    : ExpressionVisitor 
{ 
    private readonly Expression _oldValue; 
    private readonly Expression _newValue; 

    public ReplaceExpressionVisitor(Expression oldValue, Expression newValue) 
    { 
     _oldValue = oldValue; 
     _newValue = newValue; 
    } 

    public override Expression Visit(Expression node) 
    { 
     if (node == _oldValue) 
      return _newValue; 
     return base.Visit(node); 
    } 
} 

// Elsewhere... 
public Expression BuildExpression(Expression parameter, string value) 
{ 
    Expression<Predicate<Object>> e1 = a => a.ToString() == value; 
    return (new ReplaceExpressionVisitor(e1.Parameters[0], parameter)).Visit(e1.Body); 
} 

进一步清理绝对是可能的(提供静态和/或扩展方法),但是这符合我的需要。