Pergunta

Eu quero escrever controles de filtragem que tomem tipo de objeto T e nome e retorno da propriedade Expression<Func<T, bool>> que verifica o valor da propriedade passada. Não quero usar a reflexão porque receio que essas expressões não possam ser usadas pelo EF. Não posso usar delegados porque C# não possui delegados para propriedades. O que posso fazer? Talvez eu deva usar uma abordagem diferente para escrever esses controles?

Aqui está minha primeira abordagem usando a reflexão:

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;
}
Foi útil?

Solução

A reflexão não é um problema aqui; A EF nem será capaz de notar a diferença. A abordagem delegada é não iniciante, a propósito (desde que você menciona EF); Em última análise, é algo como:

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

Observe que você pode facilitar o Expression.PropertyOrField(propertyName); A razão pela qual não usei isso aqui é que é muito útil conhecer o tipo de membro (prop.PropertyType) ao criar a constante - caso contrário, você poderá obter problemas com nulos.

Outras dicas

Eu sei disso uma resposta antiga, mas se alguém vê isso, eu construí este projeto:

https://github.com/poweredsoft/dynamiclinq

Que deve ser download no NuGet também:

https://www.nuget.org/packages/poweredsoft.dynamiclinq

E você pode simplesmente fazer

query.Where("FirstName", ConditionOperators.Equal, "David");
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top