繁体   English   中英

如何重载 LINQ string.Contains()?

[英]How do I overload LINQ string.Contains()?

对于我正在实现的通用过滤器,我需要修改以下内容以接受将在 Where 方法中搜索的列名,例如:

        public IQueryable<TEntity> GetEntities(string val)
        {
            TEntity entity = _DbContext.Set<TEntity>()
                 .Where(e => e.Col1.Contains(val));
            return entities;
        }

改为

        public IQueryable<TEntity> GetEntities(string val, string colName)
        {
            TEntity entity = _DbContext.Set<TEntity>()
                 .WhereContains(val, colName);
            return entities;
        }

colName 是字符串列的名称。

我查看了https://blog.jeremylikness.com/blog/dynamically-build-linq-expressions/但无法根据我的需要修改那里的示例。 答案应该是

public static IQueryable<TEntity> WhereContains<TEntity>(this IQueryable<TEntity> query, string value, string colName)
                    where TEntity : class
{
...
...
}

但我不能让它工作......

好的,找到了一个很好的参考并且能够修改它:

public static IQueryable<T> TextFilter<T>(IQueryable<T> source, string[] colNames, string[] terms)
{
    if (colNames.Length == 0) return source;

    // T is a compile-time placeholder for the element type of the query.
    Type elementType = typeof(T);

    // Get all the properties on this specific type for colNames.
    List<PropertyInfo> props = new List<PropertyInfo>();
    for (int i = 0; i < colNames.Length; i++)
    {
        PropertyInfo prop = elementType.GetProperties().Where(x => x.PropertyType == typeof(string) && x.Name.ToLower() == colNames[i].ToLower()).FirstOrDefault();
        if (prop == null) { return source; }
        props.Add(prop);
    }

    // Get the right overload of String.Contains.  Can be replaced e.g. with "Contains"
    MethodInfo containsMethod = typeof(string).GetMethod("StartsWith", new[] { typeof(string) })!;

    // Create a parameter for the expression tree:
    // the 'x' in 'x => x.PropertyName.Contains("term")'
    // The type of this parameter is the query's element type
    ParameterExpression prm = Expression.Parameter(elementType);

    // Map each property to an expression tree node
    List<Expression> expressions = new List<Expression>();
    for (int i = 0; i < colNames.Length; i++)
    {
        expressions.Add(
            Expression.Call(
                Expression.Property(
                    prm,
                    props.ElementAt(i)
                ),
                containsMethod,
                Expression.Constant(terms[i])
            )
        );
    }

    // Combine all the resultant expression nodes using ||
    Expression body = expressions
        .Aggregate(
            (prev, current) => Expression.And(prev, current)
        );

    // Wrap the expression body in a compile-time-typed lambda expression
    Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(body, prm);

    // Because the lambda is compile-time-typed (albeit with a generic parameter), we can use it with the Where method
    return source.Where(lambda);
}

我无法将此作为扩展工作,因此调用它是通过以下方式完成的:

var qry= QueryableExtensions.TextFilter(_crudApiDbContext.Set<TEntity>()
    .Where(entity => entity.someColumn==someValue),
    filters.Keys.ToArray(), filters.Values.ToArray());
List<TEntity> entities = await qry
            .Skip(pageSize * (page - 1)).Take(pageSize).ToListAsync();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM