Generieren Sie Expression <> für die Filterung durch eine willkürliche Eigenschaft
-
05-07-2019 - |
Frage
Ich möchte Filtersteuerungen schreiben, die den Objekttyp einnehmen T
und Eigenschaftsname und Rückgabe Expression<Func<T, bool>>
Dieser prüft den Wert der übergebenen Eigenschaft. Ich möchte keine Reflexion verwenden, weil ich befürchte, dass solche Ausdrücke von EF nicht verwendet werden können. Ich kann Delegierte nicht verwenden, da C# keine Delegierten für Eigenschaften hat. Was kann ich machen? Vielleicht sollte ich einen anderen Ansatz zum Schreiben dieser Kontrollen verwenden?
Hier ist mein erster Ansatz mit Reflexion:
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;
}
Lösung
Reflexion ist hier kein Problem. EF kann den Unterschied nicht einmal bemerken. Der Delegate-Ansatz ist übrigens ein Nichtstarter (da Sie EF erwähnen); Letztendlich ist es so etwas wie:
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);
}
Beachten Sie, dass Sie es einfacher machen können Expression.PropertyOrField(propertyName)
; Der Grund, warum ich das hier nicht benutzt habe, ist, dass es sehr praktisch ist, das Mitgliedstyp zu kennen (prop.PropertyType
) Beim Erstellen der Konstante - sonst können Sie Probleme mit Nulls bekommen.
Andere Tipps
Ich kenne das eine alte Antwort, aber wenn jemand das sieht, habe ich dieses Projekt gebaut:
https://github.com/poweredsoft/dynamiclinq
Das sollte auch auf Nuget heruntergeladen werden:
https://www.nuget.org/packages/poweredsoft.dynamiclinq
Und du könntest es einfach tun
query.Where("FirstName", ConditionOperators.Equal, "David");