我为 IQueryable 创建了一个通用搜索扩展方法,使您能够搜索单个属性以查看其中是否包含搜索词。
http://jnye.co/Posts/6/c%23-generic-search-extension-method-for-iqueryable
我现在想让用户选择多个属性以在每个属性中进行搜索,匹配是否有任何属性包含文本。
编码:
用户输入以下代码来执行此搜索:
string searchTerm = "Essex";
context.Clubs.Search(searchTerm, club => club.Name, club => club.County)
//Note: If possible I would rather something closer to the following syntax...
context.Clubs.Search(club => new[]{ club.Name, club.County}, searchTerm);
// ... or, even better, something similar to this...
context.Clubs.Search(club => new { club.Name, club.County}, searchTerm);
这将返回任何名称中带有“Essex”或县的高尔夫球杆。
public static IQueryable<TSource> Search<TSource>(this IQueryable<TSource> source, string searchTerm, params Expression<Func<TSource, string>>[] stringProperties)
{
if (String.IsNullOrEmpty(searchTerm))
{
return source;
}
// The lamda I would like to reproduce:
// source.Where(x => x.[property1].Contains(searchTerm)
// || x.[property2].Contains(searchTerm)
// || x.[property3].Contains(searchTerm)...)
//Create expression to represent x.[property1].Contains(searchTerm)
var searchTermExpression = Expression.Constant(searchTerm);
//Build parameters
var parameters = stringProperties.SelectMany(prop => prop.Parameters);
Expression orExpression = null;
//Build a contains expression for each property
foreach (var stringProperty in stringProperties)
{
var checkContainsExpression = Expression.Call(stringProperty.Body, typeof(string).GetMethod("Contains"), searchTermExpression);
if (orExpression == null)
{
orExpression = checkContainsExpression;
}
//Build or expression for each property
orExpression = Expression.OrElse(orExpression, checkContainsExpression);
}
var methodCallExpression = Expression.Call(typeof(Queryable),
"Where",
new Type[] { source.ElementType },
source.Expression,
Expression.Lambda<Func<TSource, bool>>(orExpression, parameters));
return source.Provider.CreateQuery<TSource>(methodCallExpression);
}
错误
如果我将提供的参数数量更改为 1:
Expression.Lambda<Func<TSource, bool>>(orExpression, parameters.First()));
我收到一个新错误:
更新