在运行时创建Lambda表达式 [英] Creating a lambda expression at runtime

查看:62
本文介绍了在运行时创建Lambda表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a repository class which has a GetAsQueryable method defined as follows:

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

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

In my calling code I typically do operations such as:

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

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

This works great; however now I want to be able to build the lambda sent into the .Where at runtime. I have tried building an expression tree as follows:

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

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

However, this yields the following exception:

类型'System.Linq.Queryable'上的通用方法'Where'与提供的类型实参和实参不兼容.如果该方法是非泛型的,则不应该提供任何类型参数.

No generic method 'Where' on type 'System.Linq.Queryable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic.

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

Why can it not find the Where method on my instance of Tracking?

推荐答案

如果要动态构建t => t.Status_Code_Id == 15,则无需使用Expression调用Where.只需创建Expression<Func<TEntity, bool>>并将其传递给Where:

If you want to build t => t.Status_Code_Id == 15 dynamically you need don't need to call Where using Expression. Just create Expression<Func<TEntity, bool>> and pass it to 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);

var results = tracking.Where(lambda).ToList();

这篇关于在运行时创建Lambda表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆