C#动态表达树用于搜索列表,使用其中(或任何)和仿制药



当前,我有一个工作辅助函数,可以创建一个简单的表达式来搜索搜索词(单词/短语(的通用实体(Tentity(。它创建以下表达式:

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

我只需要扩展此助手即可搜索搜索词中的每个单词(例如searchText:'red shirt' -> searchterms:['red','shirt'','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 );
        }

应该是:

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

我已经放入or中所有由各种属性生成的各种表达式(方法末尾的Aggregate(。

最新更新