Domanda

Voglio scrivere controlli di filtro che accettano il tipo di oggetto T e il nome della proprietà e restituiscono Expression < Func < T, bool > > che controlla il valore della proprietà passata. Non voglio usare la riflessione perché temo che tali espressioni non possano essere utilizzate da EF. Non posso usare i delegati perché C # non ha delegati per le proprietà. Cosa posso fare? Forse dovrei usare un approccio diverso per scrivere questi controlli?

Ecco il mio primo approccio usando la riflessione:

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;
}
È stato utile?

Soluzione

La riflessione non è un problema qui; EF non sarà nemmeno in grado di notare la differenza. L'approccio delegato è un non-principiante, tra l'altro (dal momento che menzioni EF); alla fine, è qualcosa del tipo:

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

Nota che puoi semplificare con Expression.PropertyOrField (nome proprietà) ; il motivo per cui non l'ho usato qui è che è molto utile conoscere il tipo di membro ( prop.PropertyType ) quando si crea la costante, altrimenti si potrebbero avere problemi con i null.

Altri suggerimenti

Conosco questa una vecchia risposta, ma se qualcuno vede questo ho costruito questo progetto:

https://github.com/PoweredSoft/DynamicLinq

Che dovrebbe essere scaricabile anche su nuget:

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

e potresti semplicemente farlo

query.Where("FirstName", ConditionOperators.Equal, "David");
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top