gpt4 book ai didi

c# - 如何在不编译的情况下从现有的 LambdaExpression 构建 LambdaExpression

转载 作者:太空狗 更新时间:2023-10-29 23:26:26 27 4
gpt4 key购买 nike

我想在不编译的情况下组合两个 LambdaExpressions。

这就是我编译它们时的样子:

    public Expression<Func<TContainer,bool>> CreatePredicate<TContainer,TMember>(
Expression<Func<TContainer,TMember>> getMemberExpression,
Expression<Func<TMember,bool>> memberPredicateExpression)
{
return x => memberPredicateExpression.Compile()(getMemberExpression.Compile()(x));
}

这显然不是从提供的参数中获取目标表达式的最快方法。此外,它还使其与不支持 C# 方法调用的查询提供程序(如 LINQ to SQL)不兼容。

据我所知,最好的方法似乎是构建一个 ExpressionVisitor 类。但是,这似乎是一项非常常见的任务。有谁知道提供这种功能的现有开源代码库?如果不是,接近 ExpressionVisitor 以使其尽可能通用的最佳方法是什么?

最佳答案

我不知道这是否是最好的方法,但你可以这样做:

public Expression<Func<TContainer,bool>> CreatePredicate<TContainer,TMember>(
Expression<Func<TContainer,TMember>> getMemberExpression,
Expression<Func<TMember,bool>> memberPredicateExpression)
{
ParameterExpression x = Expression.Parameter(typeof(TContainer), "x");
return Expression.Lambda<Func<TContainer, bool>>(
Expression.Invoke(
memberPredicateExpression,
Expression.Invoke(
getMemberExpression,
x)),
x);
}

用法:

var expr = CreatePredicate(
(Foo f) => f.Bar,
bar => bar % 2 == 0);

结果:

x => Invoke(bar => ((bar % 2) == 0), Invoke(f => f.Bar, x))

我想得到像 x => x.Bar % 2 == 0 这样的东西会更好,但它可能会更难......


编辑:实际上,使用表达式访问者并不难:

public Expression<Func<TContainer,bool>> CreatePredicate<TContainer,TMember>(
Expression<Func<TContainer,TMember>> getMemberExpression,
Expression<Func<TMember,bool>> memberPredicateExpression)
{
return CombineExpressionVisitor.Combine(
getMemberExpression,
memberPredicateExpression);
}

class CombineExpressionVisitor : ExpressionVisitor
{
private readonly ParameterExpression _parameterToReplace;
private readonly Expression _replacementExpression;
private CombineExpressionVisitor(ParameterExpression parameterToReplace, Expression replacementExpression)
{
_parameterToReplace = parameterToReplace;
_replacementExpression = replacementExpression;
}

public static Expression<Func<TSource, TResult>> Combine<TSource, TMember, TResult>(
Expression<Func<TSource, TMember>> memberSelector,
Expression<Func<TMember, TResult>> resultSelector)
{
var visitor = new CombineExpressionVisitor(
resultSelector.Parameters[0],
memberSelector.Body);
return Expression.Lambda<Func<TSource, TResult>>(
visitor.Visit(resultSelector.Body),
memberSelector.Parameters);
}

protected override Expression VisitParameter(ParameterExpression parameter)
{
if (parameter == _parameterToReplace)
return _replacementExpression;
return base.VisitParameter(parameter);
}
}

它给出以下表达式:

f => ((f.Bar % 2) == 0)

关于c# - 如何在不编译的情况下从现有的 LambdaExpression 构建 LambdaExpression,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5361957/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com