Генерация выражения <> для фильтрации по произвольному свойству - PullRequest
2 голосов
/ 11 сентября 2009

Я хочу написать фильтрующие элементы управления, которые принимают тип объекта T и имя свойства и возвращают Expression<Func<T, bool>>, который проверяет значение переданного свойства. Я не хочу использовать рефлексию, потому что боюсь, что такие выражения не могут быть использованы EF. Я не могу использовать делегаты, потому что C # не имеет делегатов для свойств. Что я могу сделать? Может быть, я должен использовать другой подход для написания этих элементов управления?

Вот мой первый подход с использованием отражения:

public string FilteringField { get; set; }
public Expression<Func<T, bool>> GetFilterExpression()
{
  if (cmbValue.SelectedIndex == 1)
    return (o => (bool)typeof(T).GetProperty(FilteringField).GetValue(o, null));
  if (cmbValue.SelectedIndex == 2)
    return (o => !(bool)typeof(T).GetProperty(FilteringField).GetValue(o, null));
  return null;
}

Ответы [ 2 ]

3 голосов
/ 11 сентября 2009

Отражение здесь не проблема; EF даже не сможет заметить разницу. Кстати, делегатский подход не является началом (поскольку вы упоминаете EF); в конечном итоге это что-то вроде:

public static IQueryable<T> Where<T>(this IQueryable<T> query,
    string propertyName, object value)
{
    PropertyInfo prop = typeof(T).GetProperty(propertyName);
    var param = Expression.Parameter(typeof(T), "x");
    var body = Expression.Equal(
        Expression.Property(param, prop),
        Expression.Constant(value, prop.PropertyType)
        );
    var predicate = Expression.Lambda<Func<T, bool>>(body, param);
    return query.Where(predicate);
}

Обратите внимание, что вы можете сделать это проще с Expression.PropertyOrField(propertyName); причина, по которой я не использовал это, заключается в том, что очень удобно знать тип члена (prop.PropertyType) при создании константы - в противном случае вы можете получить проблемы с нулями.

0 голосов
/ 28 февраля 2018

Я знаю, что это старый ответ, но если кто-то видит это, я построил этот проект:

https://github.com/PoweredSoft/DynamicLinq

Который также должен быть загружен на nuget:

https://www.nuget.org/packages/PoweredSoft.DynamicLinq

и вы могли бы просто сделать

query.Where("FirstName", ConditionOperators.Equal, "David");
...