2015-07-14 2 views
4

У меня есть хранилище класса, который имеет метод 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; 
     } 
    } 
} 

В моем вызывающем коде я обычно делают такие операции, как:

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

это работает Великий; однако теперь я хочу, чтобы можно было построить лямбду, отправленную в .Where во время выполнения. Я пытался строить expression tree следующим образом:

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

Однако, это дает следующее исключение:

Нет общий метод "Где по типу«System.Linq.Queryable»совместит с прилагаемым введите аргументы и аргументы. Аргументы типа не должны предоставляться, если метод не является общим.

Почему не удается найти способ Where на мой случай Tracking?

ответ

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); 
var results = tracking.Where(lambda).ToList(); 
+0

Мне не хватало 'Expression.Parameter (typeof (Tracking)," t ");' piece. Возможность построить лямбда для перехода в метод «.Where» - это именно то, что я хотел сделать! @MarcinJuraszek Dziękuję бардзо! – codechurn

0

Помните, что .Where() имеет общую подпись. При использовании выражения лямбда вам не нужно указывать общие общие параметры, поскольку компилятор может вывести типы для вас, но когда вы используете рефлексию, вам нужно создать общую подпись для вызова на основе типов с которыми вы имеете дело.

Смежные вопросы