如何在 C# 中将 LambdaExpression 转换为 Expression<Func<T,bool>>
How to convert LambdaExpression to Expression<Func<T,bool>> in C#
我有以下代码根据我的 SearchTerm
输入在 运行 时间生成 LambdaExpression
。我正在尝试构建一个动态的 where
子句。但是我一直在研究如何从 LambdaExpression
转换为 Expression<Func<T,bool>>
private static Expression<Func<T,bool>> GetSearchAppliedQuery(IEnumerable<SearchTerm> terms)
{
var parameterExpression = ExpressionHelper.Parameter<T>();
Expression finalExpression = Expression.Constant(true);
Expression subExpression = Expression.Constant(false);
// Build up the LINQ Expression backwards:
// query = query.Where(x => x.Property == "Value" && (x.AnotherProperty == "Value" || x.SomeAnotherProperty == "Value"));
foreach (var term in terms)
{
var hasMultipleTerms = term.EntityName?.Contains(',') ?? false;
if (hasMultipleTerms)
{
var entityTerms = term.EntityName.Split(',');
foreach (var entityTerm in entityTerms)
{
term.EntityName = entityTerm;
// x => x.Property == "Value" || x.AnotherProperty == "Value"
subExpression = Expression.OrElse(subExpression, GetComparisonExpression(term, parameterExpression));
}
}
// x => x.Property == "Value" && x.AnotherProperty == "Value"
finalExpression = Expression.AndAlso(finalExpression, hasMultipleTerms ? subExpression : GetComparisonExpression(term, parameterExpression));
}
// x => x.Property == "Value" && (x.AnotherProperty == "Value" || x.SomeAnotherProperty == "Value")
var lambdaExpression = ExpressionHelper.GetLambda<T, bool>(parameterExpression, finalExpression);
// How to do this conversion??
Expression<Func<T,bool>> returnValue = ..??;
return returnValue;
}
我正在尝试应用上述方法的结果来获取如下所示的查询:
public static IQueryable<T> GetQuery(IQueryable<T> inputQuery, ISpecification<T> specification)
{
var query = inputQuery;
// modify the IQueryable using the specification's criteria expression
if (specification.Criteria != null)
{
query = query.Where(specification.Criteria);
}
...
return query;
}
所以我的最终查询看起来像,
query = query.Where(x => x.Property == "Value" && (x.AnotherProperty == "Value" || x.SomeAnotherProperty == "Value"))
编辑-1:
按照@Ivan Stoev
的要求添加 ExpressionHelper.GetLambda
方法
public static class ExpressionHelper
{
public static LambdaExpression GetLambda<TSource, TDest>(ParameterExpression obj, Expression arg)
{
return GetLambda(typeof(TSource), typeof(TDest), obj, arg);
}
public static LambdaExpression GetLambda(Type source, Type dest, ParameterExpression obj, Expression arg)
{
var lambdaBuilder = GetLambdaFuncBuilder(source, dest);
return (LambdaExpression)lambdaBuilder.Invoke(null, new object[] { arg, new[] { obj } });
}
private static MethodInfo GetLambdaFuncBuilder(Type source, Type dest)
{
var predicateType = typeof(Func<,>).MakeGenericType(source, dest);
return LambdaMethod.MakeGenericMethod(predicateType);
}
}
我是不是遗漏了一些非常基本的东西或者做错了什么?请协助。
用于获取 lambda 表达式的 ExpressionHelper.GetLambda<T, bool>
方法隐藏了其实际类型,即所需的 Expression<Func<T, bool>>
,因此您只需要使用强制转换运算符:
return (Expression<Func<T, bool>>)lambdaExpression;
或者更好,要么将 ExpressionHelper.GetLambda<TSource, TDest>
的结果类型更改为 Expression<Func<TSource, TDest>>
,要么不使用该辅助方法 - 当您在编译时知道泛型类型参数时,只需使用一个 if通用 Expression.Lambda 方法(ExpressionHelper.GetLambda<TSource, TDest>
似乎等同于 Expression.Lambda<Func<TSource, TDest>>
),例如
var lambdaExpression = Expression.Lambda<Func<T, bool>>(parameterExpression, finalExpression);
我有以下代码根据我的 SearchTerm
输入在 运行 时间生成 LambdaExpression
。我正在尝试构建一个动态的 where
子句。但是我一直在研究如何从 LambdaExpression
转换为 Expression<Func<T,bool>>
private static Expression<Func<T,bool>> GetSearchAppliedQuery(IEnumerable<SearchTerm> terms)
{
var parameterExpression = ExpressionHelper.Parameter<T>();
Expression finalExpression = Expression.Constant(true);
Expression subExpression = Expression.Constant(false);
// Build up the LINQ Expression backwards:
// query = query.Where(x => x.Property == "Value" && (x.AnotherProperty == "Value" || x.SomeAnotherProperty == "Value"));
foreach (var term in terms)
{
var hasMultipleTerms = term.EntityName?.Contains(',') ?? false;
if (hasMultipleTerms)
{
var entityTerms = term.EntityName.Split(',');
foreach (var entityTerm in entityTerms)
{
term.EntityName = entityTerm;
// x => x.Property == "Value" || x.AnotherProperty == "Value"
subExpression = Expression.OrElse(subExpression, GetComparisonExpression(term, parameterExpression));
}
}
// x => x.Property == "Value" && x.AnotherProperty == "Value"
finalExpression = Expression.AndAlso(finalExpression, hasMultipleTerms ? subExpression : GetComparisonExpression(term, parameterExpression));
}
// x => x.Property == "Value" && (x.AnotherProperty == "Value" || x.SomeAnotherProperty == "Value")
var lambdaExpression = ExpressionHelper.GetLambda<T, bool>(parameterExpression, finalExpression);
// How to do this conversion??
Expression<Func<T,bool>> returnValue = ..??;
return returnValue;
}
我正在尝试应用上述方法的结果来获取如下所示的查询:
public static IQueryable<T> GetQuery(IQueryable<T> inputQuery, ISpecification<T> specification)
{
var query = inputQuery;
// modify the IQueryable using the specification's criteria expression
if (specification.Criteria != null)
{
query = query.Where(specification.Criteria);
}
...
return query;
}
所以我的最终查询看起来像,
query = query.Where(x => x.Property == "Value" && (x.AnotherProperty == "Value" || x.SomeAnotherProperty == "Value"))
编辑-1: 按照@Ivan Stoev
的要求添加ExpressionHelper.GetLambda
方法
public static class ExpressionHelper
{
public static LambdaExpression GetLambda<TSource, TDest>(ParameterExpression obj, Expression arg)
{
return GetLambda(typeof(TSource), typeof(TDest), obj, arg);
}
public static LambdaExpression GetLambda(Type source, Type dest, ParameterExpression obj, Expression arg)
{
var lambdaBuilder = GetLambdaFuncBuilder(source, dest);
return (LambdaExpression)lambdaBuilder.Invoke(null, new object[] { arg, new[] { obj } });
}
private static MethodInfo GetLambdaFuncBuilder(Type source, Type dest)
{
var predicateType = typeof(Func<,>).MakeGenericType(source, dest);
return LambdaMethod.MakeGenericMethod(predicateType);
}
}
我是不是遗漏了一些非常基本的东西或者做错了什么?请协助。
用于获取 lambda 表达式的 ExpressionHelper.GetLambda<T, bool>
方法隐藏了其实际类型,即所需的 Expression<Func<T, bool>>
,因此您只需要使用强制转换运算符:
return (Expression<Func<T, bool>>)lambdaExpression;
或者更好,要么将 ExpressionHelper.GetLambda<TSource, TDest>
的结果类型更改为 Expression<Func<TSource, TDest>>
,要么不使用该辅助方法 - 当您在编译时知道泛型类型参数时,只需使用一个 if通用 Expression.Lambda 方法(ExpressionHelper.GetLambda<TSource, TDest>
似乎等同于 Expression.Lambda<Func<TSource, TDest>>
),例如
var lambdaExpression = Expression.Lambda<Func<T, bool>>(parameterExpression, finalExpression);