2017-04-18 11 views
0

現在、私は、検索用語(単一単語/フレーズ)を一般的なエンティティ(TEntity)で検索する単純な式を作成する作業ヘルパ関数を持っています。 >のSearchTerms - 「赤シャツ」:[「赤」、「Tシャツ」これは、次の式を作成:Where(またはAny)とジェネリックスを使用する検索リストの動的式ツリー

q => q.Product.ProductTitle.Contains(searchText: 'red shirt') 

を私は単純に検索用語(たとえば、検索テキストに含まれる各単語を検索するには、このヘルパーを拡張する必要があります])

var searchTerms = searchText.ToLower().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); 
searchTerms.Any(s => !q.Product.ProductTitle.ToLower().Contains(s)) 

この機能は以下のとおりです。コードを完成させる必要があります。

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); 
     } 
+1

文字列を一重引用符で囲むのはなぜですか( '' red shirt'')?複数の文字列を受け入れるように拡張したい場合、これを関数argsとして使うことができます: '(List searchPropertiesList、SearchType searchType、params string [] args)'なら、 1(またはそれ以上)の 'args'が渡されます。https://msdn.microsoft.com/en-us/library/w5zay9db.aspx –

+0

ご意見ありがとうございます。私は今後の行動の更新や変更を見ていきます。 –

答えて

0

それは次のようになります。私は、さまざまなプロパティ(メソッドの終わり近くAggregate)によって生成されorすべての様々な表情に置かれている

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; 
} 

関連する問題