根据搜索查询的值搜索IQueryable T集合的每个属性值。如何一起测试NOT NULL和CONTAINS?

时间:2014-04-08 18:52:42

标签: c# linq generics expression-trees iqueryable

我正在尝试搜索IQ的可识别集合的每个属性值与搜索查询的值。我有以下功能,想知道我如何一起测试NOT NULL和CONTAINS?

private Expression<Func<T, bool>> PropertySearch
{
  get
  {
     // Object that is passed to the lambda expression
     ParameterExpression instance = Expression.Parameter(typeof(T), "val");
     Expression whereExpr = Expression.Constant(true); // default is val => True

     var _properties = typeof(T).GetProperties();
     foreach (var prop in _properties)
     {
        var query = _httpRequest["query"].ToLower();
        var property = Expression.Property(instance, prop);
        var toStringCall = Expression.Call(Expression.Call(
            property,
            "ToString", 
            new Type[0]), 
            typeof(string).GetMethod("ToLower", new Type[0]));
        whereExpr = Expression.And(whereExpr, 
            Expression.Call(toStringCall, typeof(string).GetMethod("Contains"), 
            Expression.Constant(query)));
     }
     return Expression.Lambda<Func<T, bool>>(whereExpr, instance);
}}

2 个答案:

答案 0 :(得分:0)

我创建了一个搜索扩展nuget包来执行此类检查。对于你的例子,我会做类似以下的事情。

注意,这是没有IDE的,因此可能会出现一些错误

/* *** Start: These can be made private reaonly fields ***/
var comparisonExpr = Expression.Constant(StringComparison.OrdinalIgnoreCase);
var zeroExpression = Expression.Constant(0)
var nullExpression = Expression.Constant(null)
MethodInfo IndexOfMethod = typeof(string).GetMethod("IndexOf", new[] { typeof(string), typeof(StringComparison) });  
/* *** End ***/

Expression finalExpression = null
ParameterExpression instance = Expression.Parameter(typeof(T), "val");
var _properties = typeof(T).GetProperties();
var query = _httpRequest["query"].ToLower();
var queryExpr = Expression.Constant(query);

foreach (var prop in _properties)
{
    //Get property
    var propertyExpr = Expression.Property(instance, prop);
    //Get property as string
    var propStringExpr = Expression.Call(property, "ToString", new Type[0]);
    //Perform IndexOf call
    var indexOfExpr = Expression.Call(propStringExpr, 
                                       IndexOfMethod, 
                                       queryExpr, 
                                       comparisonExpr);

    // Check index of is greater than or equal to zero
    var containsExpr = Expression.GreaterThanOrEqual(containsExpr, zeroExpression);

    if(finalExpression == null)
    {
        finalExpression = containsExp;
    }
    else
    {
        finalExpression = Expression.AndAlso(containsExpr);
    }
}

return Expression.Lambda<Func<T, bool>>(finalExpression, instance);

我已删除ToLower()的需要,而是使用IndexOf字符串比较类型

如果您想了解我是如何实现类似功能的,请查看Github上的NinjaNye.SearchExtensions

https://github.com/ninjanye/SearchExtensions

如果您想搜索IQueryable的集合,可以使用NinjaNye.SearchExtensions,如下所示

string query = _httpRequest["query"];
var result = data.SearchAll().Containing(query);

这将搜索所有字符串属性(不是您上面的所有属性),只返回任何属性与搜索字词匹配的字段。

希望这有帮助

答案 1 :(得分:0)

您可以使用PredicateBuilder,这样您就不必自己弄乱表达树了。

相关问题