C#使用Where(或Any)和泛型搜索列表的动态表达式树
目前,我有一个工作助手函数,可以创建一个简单的表达式来搜索通用实体(TEntity)中的搜索词(单个单词/短语)。它创建以下表达式:C#使用Where(或Any)和泛型搜索列表的动态表达式树,c#,linq,generics,lambda,expression,C#,Linq,Generics,Lambda,Expression,目前,我有一个工作助手函数,可以创建一个简单的表达式来搜索通用实体(TEntity)中的搜索词(单个单词/短语)。它创建以下表达式: q => q.Product.ProductTitle.Contains( searchText: 'red shirt' ) 我只需要扩展这个帮助程序来搜索搜索词中包含的每个词(例如searchText:'red shirt'-->searchTerms:['red','shirt']) 下面列出了该函数-我已经对需要完成的代码进行了注释 pub
q => q.Product.ProductTitle.Contains( searchText: 'red shirt' )
我只需要扩展这个帮助程序来搜索搜索词中包含的每个词(例如searchText:'red shirt'-->searchTerms:['red','shirt'])
下面列出了该函数-我已经对需要完成的代码进行了注释
public static Expression<Func<TEntity, bool>> CreateSearchQuery( List<PropertyInfo> searchPropertiesList, string searchText, SearchType searchType = SearchType.Contains )
{
if( string.IsNullOrWhiteSpace( searchText ) || searchPropertiesList == null || searchPropertiesList.Count <= 0 )
{
return null;
}
var searchTerms = searchText.ToLower().Split( new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries ).ToList();
var searchExpressionList = new List<Expression<Func<TEntity, bool>>>();
foreach( var property in searchPropertiesList.Where( x => x.GetCustomAttributes( false ).Any( c => c.GetType() != typeof( NotMappedAttribute ) ) ) )
{
//search param
var searchParam = Expression.Parameter( typeof( string ), "s" );
//search type
var searchTypeMethod = typeof( string ).GetMethod( searchType.ToString(), new[] { typeof( string ) } );
//entity expression.
var entityParam = Expression.Parameter( typeof( TEntity ), "q" );
var entityProperty = Expression.Property( entityParam, property );
var entityExpression = Expression.Call(
Expression.Call( entityProperty, typeof( string ).GetMethod( "ToLower", System.Type.EmptyTypes ) ),
searchTypeMethod,
Expression.Call( searchParam, typeof( string ).GetMethod( "ToLower", System.Type.EmptyTypes ) )
);
var entityPredicateBody = Expression.Lambda<Func<TEntity, bool>>( entityExpression, entityParam );
////TODO: CONSIDER EACH TERM AND CREATE WHERE/ANY EXPRESSION
//searchTerms.Any( s => !q.Product.ProductTitle.ToLower().Contains( s ) )
//var filterExpression = Expression.Call(
// typeof( Enumerable ),
// "Where",
// new[] { typeof( TEntity ) },
// searchParam,
// entityPredicateBody );
//var expressionBody = Expression.Lambda<Func<TEntity, bool>>( filterExpression, searchParam );
//TODO: REPLACE WITH NEW EXPRESSION (expressionBody)
searchExpressionList.Add( entityPredicateBody );
}
公共静态表达式CreateSearchQuery(列表searchPropertiesList,字符串searchText,SearchType SearchType=SearchType.Contains)
{
if(string.IsNullOrWhiteSpace(searchText)| | searchPropertiesList==null | | | searchPropertiesList.Count x.GetCustomAttributes(false).Any(c=>c.GetType()!=typeof(NotMappedAttribute)))
{
//搜索参数
var searchParam=Expression.Parameter(typeof(string),“s”);
//搜索类型
var searchTypeMethod=typeof(string).GetMethod(searchType.ToString(),new[]{typeof(string)});
//实体表达式。
var entityParam=表达式参数(typeof(tenty),“q”);
var entityProperty=Expression.Property(entityParam,Property);
var entityExpression=Expression.Call(
Expression.Call(entityProperty,typeof(string).GetMethod(“ToLower”,System.Type.EmptyTypes)),
搜索类型方法,
Expression.Call(searchParam,typeof(string).GetMethod(“ToLower”,System.Type.EmptyTypes))
);
var entityPredicateBody=Expression.Lambda(entityExpression,entityParam);
///todo:考虑每个术语并创建何处/任何表达式
//searchTerms.Any(s=>!q.Product.ProductTitle.ToLower().Contains)
//var filtereexpression=Expression.Call(
//类型(可枚举),
//“哪里”,
//新[]{typeof(tenty)},
//searchParam,
//实体预测体);
//var expressionBody=Expression.Lambda(filterExpression,searchParam);
//TODO:替换为新表达式(expressionBody)
searchExpressionList.Add(entityPredicateBody);
}
它应该是:
public static Expression<Func<TEntity, bool>> CreateSearchQuery<TEntity>(List<PropertyInfo> properties, string text, SearchType searchType = SearchType.Contains)
{
if (string.IsNullOrWhiteSpace(text) || properties == null || properties.Count == 0)
{
return null;
}
// For comparison
//Expression<Func<ProductContainer, bool>> exp = q => searchText.Any(x => q.Product.ProductTitle.ToLower().Contains(x));
var expressions = new List<Expression>();
var entity = Expression.Parameter(typeof(TEntity), "q");
//search type
var searchMethod = typeof(string).GetMethod(searchType.ToString(), new[] { typeof(string) });
//search terms
var searchTerms = Expression.Constant(text.ToLower().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
//search param
var str = Expression.Parameter(typeof(string), "s");
foreach (var property in properties.Where(
x => x.GetCustomAttribute<NotMappedAttribute>() == null))
{
var entityProperty = Expression.Property(entity, property);
var toLower = Expression.Call(entityProperty, "ToLower", Type.EmptyTypes);
var contains = Expression.Call(toLower, searchMethod, str);
var anyExpression = Expression.Lambda<Func<string, bool>>(contains, str);
var any = Expression.Call(typeof(Enumerable), "Any", new[] { typeof(string) }, searchTerms, anyExpression);
expressions.Add(any);
}
var ors = expressions.Aggregate((x, y) => Expression.Or(x, y));
var exp = Expression.Lambda<Func<TEntity, bool>>(ors, entity);
return exp;
}
公共静态表达式CreateSearchQuery(列表属性、字符串文本、SearchType SearchType=SearchType.Contains)
{
if(string.IsNullOrWhiteSpace(text)| | properties==null | | | properties.Count==0)
{
返回null;
}
//作比较
//表达式exp=q=>searchText.Any(x=>q.Product.ProductTitle.ToLower().Contains(x));
var表达式=新列表();
var实体=表达式参数(typeof(tenty),“q”);
//搜索类型
var searchMethod=typeof(string).GetMethod(searchType.ToString(),new[]{typeof(string)});
//搜索词
var searchTerms=Expression.Constant(text.ToLower().Split(new[]{''},StringSplitOptions.removeMptyEntries));
//搜索参数
var str=Expression.Parameter(typeof(string),“s”);
foreach(properties.Where中的var属性(
x=>x.GetCustomAttribute()==null))
{
var entityProperty=Expression.Property(实体,属性);
var-toLower=Expression.Call(entityProperty,“toLower”,Type.EmptyTypes);
var contains=Expression.Call(toLower、searchMethod、str);
var anyExpression=Expression.Lambda(contains,str);
var any=Expression.Call(typeof(Enumerable),“any”,new[]{typeof(string)},searchTerms,anyExpression);
添加(任何);
}
var ors=表达式.聚合((x,y)=>表达式.或(x,y));
var exp=表达式.Lambda(ors,实体);
返回经验;
}
我已经输入了
或由各种属性生成的所有各种表达式(方法末尾附近的聚合)为什么要将字符串用单引号括起来('red shirt'
)?如果您希望能够扩展它以接受多个字符串,可以将其用作函数args:(List searchproperties List、SearchType SearchType、params string[]args)
,那么您只需要处理1(或更多)args
已传递。请参阅:感谢您的反馈,Zac。我将在将来查看更新或更改行为。
public static Expression<Func<TEntity, bool>> CreateSearchQuery<TEntity>(List<PropertyInfo> properties, string text, SearchType searchType = SearchType.Contains)
{
if (string.IsNullOrWhiteSpace(text) || properties == null || properties.Count == 0)
{
return null;
}
// For comparison
//Expression<Func<ProductContainer, bool>> exp = q => searchText.Any(x => q.Product.ProductTitle.ToLower().Contains(x));
var expressions = new List<Expression>();
var entity = Expression.Parameter(typeof(TEntity), "q");
//search type
var searchMethod = typeof(string).GetMethod(searchType.ToString(), new[] { typeof(string) });
//search terms
var searchTerms = Expression.Constant(text.ToLower().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
//search param
var str = Expression.Parameter(typeof(string), "s");
foreach (var property in properties.Where(
x => x.GetCustomAttribute<NotMappedAttribute>() == null))
{
var entityProperty = Expression.Property(entity, property);
var toLower = Expression.Call(entityProperty, "ToLower", Type.EmptyTypes);
var contains = Expression.Call(toLower, searchMethod, str);
var anyExpression = Expression.Lambda<Func<string, bool>>(contains, str);
var any = Expression.Call(typeof(Enumerable), "Any", new[] { typeof(string) }, searchTerms, anyExpression);
expressions.Add(any);
}
var ors = expressions.Aggregate((x, y) => Expression.Or(x, y));
var exp = Expression.Lambda<Func<TEntity, bool>>(ors, entity);
return exp;
}