重载 LINQ List.Contains() 以接受列名

Overload for LINQ List.Contains() to accept column name

我想修改以下程序

        public async Task<IActionResult> GetMany(List<int> values)
        {
             List<TEntity> entities = await _crudApiDbContext.Set<TEntity>()
                    .Where(entity => values.Contains(entity.Id)).ToListAsync();
             return new OkObjectResult(entities);
        }

接受将在 Contains 方法中搜索的列名,例如:

        public async Task<IActionResult> GetMany(List<int> values, string colName)
        {
             List<TEntity> entities = await _crudApiDbContext.Set<TEntity>()
                    .Where(entity => values.Contains<TEntity>(colName)).ToListAsync();
             return new OkObjectResult(entities);
        }

我试过重载 Contains 并使用表达式树,但我迷路了...

有什么想法吗?

引入以下扩展方法,它应该按集合过滤任何实体类型:

public static class QueryableExtensions
{
    public static IQueryable<TEntity> FilterByList<TEntity, TKey>(this IQueryable<TEntity> query, IEnumerable<TKey> values, string colName) 
        where TEntity : class
    {
        var param = Expression.Parameter(typeof(TEntity), "e");
        var propAccess = Expression.PropertyOrField(param, colName);
        var listExpr = Expression.Constant(values);

        var predicate = Expression.Call(typeof(Enumerable), "Contains", new[] {typeof(TKey)}, listExpr,
            propAccess);

        var predicateLambda = Expression.Lambda<Func<TEntity, bool>>(predicate, param);

        return query.Where(predicateLambda);
    }
}

并将您的 GetMany 重写为这个变体:

public async Task<IActionResult> GetMany<TEntity>(List<int> values, string colName)
{
    var entities = await _crudApiDbContext.Set<TEntity>()
        .FilterByList(values, colName)
        .ToListAsync();
    return new OkObjectResult(entities);
}