C# 用表达式实现LINQ滤波器
在MVC4中,我向用户提供搜索框来搜索表中的任何值。 所以我在C语言中实现了服务器端的通用过滤条件# 需要帮助组合多个表达式以形成单个表达式C# 用表达式实现LINQ滤波器,c#,linq,C#,Linq,在MVC4中,我向用户提供搜索框来搜索表中的任何值。 所以我在C语言中实现了服务器端的通用过滤条件# 需要帮助组合多个表达式以形成单个表达式 Expression<Func<T, bool>> 到目前为止,我已经实施了 /// <summary> /// string[] properties property.Name (MenuText, ActionName), including deeper Mapping names such a
Expression<Func<T, bool>>
到目前为止,我已经实施了
/// <summary>
/// string[] properties property.Name (MenuText, ActionName), including deeper Mapping names such as (Role.Name)
/// </summary>
public static Expression<Func<T, bool>> FilterKey<T>(string filterText, params string[] properties)
{
ParameterExpression parameter = Expression.Parameter(typeof (T));
Expression[] propertyExpressions = properties.Select(
x => !string.IsNullOrEmpty(x) ? GetDeepPropertyExpression(parameter, x) : null).ToArray();
Expression<Func<T, bool>> predicate = PredicateBuilder.False<T>();
foreach (Expression expression in propertyExpressions)
{
var toLower = Expression.Call(expression, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
var like = Expression.Call(toLower, typeof(string).GetMethod("Contains"), Expression.Constant(filterText.ToLower()));
//TODO: Combine expressions to form single Expression<Func<T, bool>> expression
}
return predicate;
}
/// <summary>
/// To Get Deeper Properties such as Role.Name Expressions
/// </summary>
private static Expression GetDeepPropertyExpression(Expression initialInstance, string property)
{
Expression result = null;
foreach (string propertyName in property.Split('.'))
{
Expression instance = result ?? initialInstance;
result = Expression.Property(instance, propertyName);
}
return result;
}
//
///string[]properties property.Name(MenuText,ActionName),包括更深层次的映射名称,如(Role.Name)
///
公共静态表达式FilterKey(字符串filterText,参数字符串[]属性)
{
ParameterExpression参数=Expression.parameter(typeof(T));
表达式[]属性表达式=属性。选择(
x=>!string.IsNullOrEmpty(x)?GetDeepPropertyExpression(参数,x):null.ToArray();
表达式谓词=PredicateBuilder.False();
foreach(propertyExpressions中的表达式)
{
var-toLower=Expression.Call(Expression,typeof(string).GetMethod(“toLower”,System.Type.EmptyTypes));
var like=Expression.Call(toLower,typeof(string).GetMethod(“Contains”),Expression.Constant(filterText.toLower());
//TODO:组合表达式以形成单个表达式
}
返回谓词;
}
///
///获取更深层次的属性,如Role.Name表达式
///
私有静态表达式GetDeepPropertyExpression(表达式initialInstance,字符串属性)
{
表达式结果=null;
foreach(property.Split('.')中的字符串propertyName)
{
表达式实例=结果??初始实例;
结果=Expression.Property(实例,propertyName);
}
返回结果;
}
我创建了一些搜索IQueryable
扩展方法,您应该能够使用这些方法
全文如下:
GitHub项目在这里(有两个额外的扩展用于或搜索:
您可能还会发现以下帖子很有用:
允许搜索多个属性的搜索扩展方法:
允许在属性上使用多个或多个搜索词的搜索扩展方法:
多亏了NinjaNye,我借用了BuildOrExpression,解决了我的问题
这是解决办法
public static Expression<Func<T, bool>> FilterKey<T>(string filterText, params string[] properties)
{
ParameterExpression parameter = Expression.Parameter(typeof (T));
Expression[] propertyExpressions = properties.Select(
x => !string.IsNullOrEmpty(x) ? GetDeepPropertyExpression(parameter, x) : null).ToArray();
Expression like= propertyExpressions.Select(expression => Expression.Call(expression, typeof (string).GetMethod("ToLower", Type.EmptyTypes))).Select(toLower => Expression.Call(toLower, typeof (string).GetMethod("Contains"), Expression.Constant(filterText.ToLower()))).Aggregate<MethodCallExpression, Expression>(null, (current, ex) => BuildOrExpression(current, ex));
return Expression.Lambda<Func<T, bool>>(like, parameter);
}
private static Expression BuildOrExpression(Expression existingExpression, Expression expressionToAdd)
{
if (existingExpression == null)
{
return expressionToAdd;
}
//Build 'OR' expression for each property
return Expression.OrElse(existingExpression, expressionToAdd);
}
private static Expression GetDeepPropertyExpression(Expression initialInstance, string property)
{
Expression result = null;
foreach (string propertyName in property.Split('.'))
{
Expression instance = result ?? initialInstance;
result = Expression.Property(instance, propertyName);
}
return result;
}
公共静态表达式FilterKey(字符串filterText,参数string[]属性)
{
ParameterExpression参数=Expression.parameter(typeof(T));
表达式[]属性表达式=属性。选择(
x=>!string.IsNullOrEmpty(x)?GetDeepPropertyExpression(参数,x):null.ToArray();
Expression like=propertyExpressions.Select(Expression=>Expression.Call(Expression,typeof(string).GetMethod(“ToLower”,Type.EmptyTypes))).Select(ToLower=>Expression.Call(ToLower,typeof(string).GetMethod(“Contains”),Expression.Constant(filterText.ToLower()).Aggregate(null,(current,ex)=>buildoreexpression(current,ex));
返回表达式.Lambda(like,parameter);
}
私有静态表达式BuildOrExpression(表达式existingExpression、表达式expressionToAdd)
{
if(existingExpression==null)
{
返回要添加的表达式;
}
//为每个属性生成“或”表达式
返回表达式.OrElse(existingExpression,expressionToAdd);
}
私有静态表达式GetDeepPropertyExpression(表达式initialInstance,字符串属性)
{
表达式结果=null;
foreach(property.Split('.')中的字符串propertyName)
{
表达式实例=结果??初始实例;
结果=Expression.Property(实例,propertyName);
}
返回结果;
}
在过去24小时内,您已经问了3次几乎相同的问题。。。
public static class QueryableExtensions
{
public static IQueryable<T> Search<T>(this IQueryable<T> source, Expression<Func<T, string>> stringProperty, string searchTerm)
{
if (String.IsNullOrEmpty(searchTerm))
{
return source;
}
// The below represents the following lamda:
// source.Where(x => x.[property] != null
// && x.[property].Contains(searchTerm))
//Create expression to represent x.[property] != null
var isNotNullExpression = Expression.NotEqual(stringProperty.Body, Expression.Constant(null));
//Create expression to represent x.[property].Contains(searchTerm)
var searchTermExpression = Expression.Constant(searchTerm);
var checkContainsExpression = Expression.Call(stringProperty.Body, typeof(string).GetMethod("Contains"), searchTermExpression);
//Join not null and contains expressions
var notNullAndContainsExpression = Expression.AndAlso(isNotNullExpression, checkContainsExpression);
var methodCallExpression = Expression.Call(typeof(Queryable),
"Where",
new Type[] { source.ElementType },
source.Expression,
Expression.Lambda<Func<T, bool>>(notNullAndContainsExpression, stringProperty.Parameters));
return source.Provider.CreateQuery<T>(methodCallExpression);
}
}
string searchTerm = "test";
var results = context.Menu.Search(menu => menu.MenuText, searchTerm).ToList();
//OR for Role name
string searchTerm = "test";
var results = context.Menu.Search(menu => menu.Role.Name, searchTerm).ToList();
public static Expression<Func<T, bool>> FilterKey<T>(string filterText, params string[] properties)
{
ParameterExpression parameter = Expression.Parameter(typeof (T));
Expression[] propertyExpressions = properties.Select(
x => !string.IsNullOrEmpty(x) ? GetDeepPropertyExpression(parameter, x) : null).ToArray();
Expression like= propertyExpressions.Select(expression => Expression.Call(expression, typeof (string).GetMethod("ToLower", Type.EmptyTypes))).Select(toLower => Expression.Call(toLower, typeof (string).GetMethod("Contains"), Expression.Constant(filterText.ToLower()))).Aggregate<MethodCallExpression, Expression>(null, (current, ex) => BuildOrExpression(current, ex));
return Expression.Lambda<Func<T, bool>>(like, parameter);
}
private static Expression BuildOrExpression(Expression existingExpression, Expression expressionToAdd)
{
if (existingExpression == null)
{
return expressionToAdd;
}
//Build 'OR' expression for each property
return Expression.OrElse(existingExpression, expressionToAdd);
}
private static Expression GetDeepPropertyExpression(Expression initialInstance, string property)
{
Expression result = null;
foreach (string propertyName in property.Split('.'))
{
Expression instance = result ?? initialInstance;
result = Expression.Property(instance, propertyName);
}
return result;
}