2017-02-18 23 views
1

Как передать свойство объекта как параметр выражения LINQ?Как передать свойство объекта как параметр выражения LINQ?

public DropdownFilter(WhatTypeHere? ABC) 
{ 
    // I want to store a selected property here 
    // ABC must be a property of TEntity 
    this.ABC = ABC; 
} 

// I want the class to encapsulate a LINQ query and just parametrize it with a property 
public override IQueryable<TEntity> Filter(IQueryable<TEntity> filteredEntityCollection, string value) 
{ 
    // ABC is a property of TEntity 
    return filteredEntityCollection.Where(this.ABC == value); 
} 

Я буду использовать его как это:

new DropdownFilter<Invoice>(invoice => invoice.SomeProperty); 

Я уже пробовал с Expression<Func<TEntity, string>> типа параметра, но это не сработало. Жалоба около

The LINQ expression node type 'Invoke' is not supported in LINQ to Entities. 

ответ

1

Вы должны вручную создать LINQ выражение. Прежде всего я хотел бы добавить второй общий параметр в класс, который будет указать тип недвижимости и типа значения, которое вы бы перейти на фильтр:

public class DropdownFilter<TEntity, TProperty> 

Далее следует передать выражение селектора свойства конструктору этого класса фильтра :

private PropertyInfo propertyInfo; 

public DropdownFilter(Expression<Func<TEntity, TProperty>> propertySelector) 
{ 
    this.propertyInfo = (PropertyInfo)((MemberExpression)propertySelector.Body).Member; 
} 

И наконец, построить лямбда-выражения для фильтрации запрашиваемых по заданному значению заданного свойства:

public IQueryable<TEntity> Filter(
    IQueryable<TEntity> filteredEntityCollection, TProperty value) 
{ 
    var param = Expression.Parameter(typeof(TEntity), "p"); 

    var lambda = Expression.Lambda<Func<TEntity, bool>>(    
     Expression.Equal(
      Expression.Property(param, propertyInfo), 
      Expression.Constant(value) 
     ), param); 

    return filteredEntityCollection.Where(lambda); 
} 

Использование:

var filter = new DropdownFilter<Invoice, string>(i => i.ABC); 
var result = filter(db.Invoices, "foo"); // strongly-typed parameter here 

Я бы добавил проверку выражения выбора свойства, переданного конструктору. Вы должны проверить, является ли это выражением MemberExpression. И вы можете verfiy тип свойства поддерживать только примитивные типы свойств.

+1

Это потрясающе, и я уверен, что это сработает, но я не могу использовать его, прежде чем я выясню, как распространять «TProperty» вверх ... так как все мои «фильтры» наследуются от базового класса, который используется как свойство списка другого объекта ... –

+0

@HristoYankov хорошо, вы можете удалить TProperty и либо использовать 'string', как вы хотели раньше (но вы должны проверить' propertyInfo.PropertyType' как строку), или вы можете использовать 'object' в качестве значения и преобразовать его в тип свойства с помощью выражения Expression.Convert (Expression.Constant (value), propertyType)' –