[英]C# - Expression parameter into another Expression using lambda?
作為WPF應用程序的一部分,我正在構建一個表達式樹並生成一個謂詞以用作過濾器。 代碼看起來像這樣:
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;
}
這是因為參數是未知類型的表達式-它可能是int,字符串,Guid或其他任何值。 問題在於,如果沒有大量評論,很難理解這里發生的事情。 我真的很想在這里使用lambda:
return parameter => parameter.ToString() == value;
問題在於這不能按預期方式工作-生成的委托將在Expression上調用ToString()而不是表達式的值 。 如果有幫助,則參數為MemberExpression。
我能夠找到一種方法,只需很少的額外代碼。 該解決方案的主要靈感來自Mark Gravell對組合兩個表達式(Expression <Func <T,bool >>)的回答。
從.net 4.0開始。 有ExpressionVistor類,它允許您構建EF安全的表達式。
Expression<TDelegate>
是從LambdaExpression派生的(如果您有興趣了解有關它們實際工作方式的更多信息,建議您查看“ LINQ-Expression Tree Visualizer”示例,該示例當前位於https://code.msdn.microsoft .com / LINQ-Expression-Tree-47608cb5 )。 這行代碼:
Expression<Predicate<Object>> e1 = a => a.ToString() == "foo";
使用單個ParameterExpression(Type:Object,ReturnType:Boolean,Body:(LogicalBinaryExpression))創建一個LambdaExpression。 使用自定義ExpressionVisitor,我們可以修改Lambda的主體以創建與之前的代碼相同的結果:
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);
}
肯定可以進行進一步的清理(提供靜態和/或擴展方法),但這可以滿足我的需求。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.