在运行时创建lambda表达式

cod*_*urn 4 c# linq lambda

我有一个存储库类,其GetAsQueryable方法定义如下:

public class Repository<TEntity> : IDisposable, IRepository<TEntity> where TEntity : class
{
    internal DbSet<TEntity> _DbSet;

    public virtual IQueryable<TEntity> GetAsQueryable(
         Expression<Func<TEntity, bool>> filter = null,
         Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
         string includeProperties = "")
    {
        IQueryable<TEntity> query = _DbSet;

        if (filter != null)
        {
            query = query.Where(filter);
        }

        foreach (var includeProperty in includeProperties.Split
            (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
        {
            query = query.Include(includeProperty);
        }

        if (orderBy != null)
        {
            return orderBy(query);
        }
        else
        {
            return query;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的调用代码中,我通常执行以下操作:

IRepository<Tracking> repoTracking = new Repository<Tracking>(context);
IQueryable<Tracking> tracking = repoTracking.GetAsQueryable();
var results = tracking.Where(t => t.Status_Code_Id == 15).ToList();
Run Code Online (Sandbox Code Playgroud)

这很好用; 但是现在我希望能够构建.Where在运行时发送到的lambda .我尝试构建表达式树,如下所示:

IRepository<Tracking> repoTracking = new Repository<Tracking>(context);
IQueryable<Tracking> tracking = repoTracking.GetAsQueryable();
var results = tracking.Where(t => t.Status_Code_Id == 15).ToList();

IRepository<Tracking> repoTracking = new Repository<Tracking>(context);
IQueryable<Tracking> tracking = repoTracking.GetAsQueryable();

ParameterExpression pe = Expression.Parameter(typeof (int), "Status_Code_Id");
LambdaExpression lambda = Expression.Lambda(Expression.Equal(pe, Expression.Constant(15)));
MethodCallExpression whereExpression = Expression.Call(
    typeof(Queryable),
    "Where",
    new Type[] { tracking.ElementType },
    tracking.Expression,
    lambda);
Run Code Online (Sandbox Code Playgroud)

但是,这会产生以下异常:

类型'System.Linq.Queryable'上没有泛型方法'Where'与提供的类型参数和参数兼容.如果方法是非泛型的,则不应提供类型参数.

为什么它Where在我的实例上找不到方法Tracking

Mar*_*zek 7

如果你想建立t => t.Status_Code_Id == 15动态的,你需要不需要调用Where使用Expression.只需创建Expression<Func<TEntity, bool>>并传递给Where:

ParameterExpression t = Expression.Parameter(typeof(Tracking), "t");
Expression statusCode = Expression.Property(t, "Status_Code_Id");
Expression comparison = Expression.Equal(statusCode, Expression.Constant(15));
Expression<Func<Tracking, bool>> lambda
    = Expression.Lambda<Func<Tracking, bool>>(comparison, t);
Run Code Online (Sandbox Code Playgroud)
var results = tracking.Where(lambda).ToList();
Run Code Online (Sandbox Code Playgroud)