Wie baue ich einen LINQ -Expressionsbaum, der mit einem generischen Objekt verglichen wird?
-
04-07-2019 - |
Frage
Ich habe ein iQueryable und ein Objekt vom Typ T.
Ich möchte iQueryable (). WO (o => o.getProperty (FieldName) == Objectoftypet.getProperty (Feldname))
Also ...
public IQueryable<T> DoWork<T>(string fieldName)
where T : EntityObject
{
...
T objectOfTypeT = ...;
....
return SomeIQueryable<T>().Where(o => o.GetProperty(fieldName) == objectOfTypeT.GetProperty(fieldName));
}
Zu Ihrer Information, GetProperty ist keine gültige Funktion. Ich brauche etwas, das diese Funktion ausführt.
Habe ich eine Gehirnschmelze am Freitagnachmittag oder ist das eine komplexe Sache?
ObjectOftypet Ich kann Folgendes machen ...
var matchToValue = Expression.Lambda(ParameterExpression
.Property(ParameterExpression.Constant(item), "CustomerKey"))
.Compile().DynamicInvoke();
Was perfekt funktioniert, jetzt brauche ich nur den zweiten Teil:
kehre misiqueyable (). Wo (o => O.GetProperty (Feldname) == MatchValue);
Lösung
Like SO:
var param = Expression.Parameter(typeof(T), "o");
var fixedItem = Expression.Constant(objectOfTypeT, typeof(T));
var body = Expression.Equal(
Expression.PropertyOrField(param, fieldName),
Expression.PropertyOrField(fixedItem, fieldName));
var lambda = Expression.Lambda<Func<T,bool>>(body,param);
return source.Where(lambda);
Ich habe einen Blog gestartet, der eine Reihe von Ausdrucksthemen abdeckt. hier.
Wenn Sie Probleme erhalten, besteht eine andere Option darin, den Wert aus dem Wert zu extrahieren objectOfTypeT
zuerst (unter Verwendung von Reflexion) und dann diesen Wert in der Expression.Constant
, aber ich vermute, es wird in Ordnung "wie es ist".
Andere Tipps
Nach dem, was ich bisher sehen kann, muss es so etwas sein wie ...
IQueryable<T>().Where(t =>
MemberExpression.Property(MemberExpression.Constant(t), fieldName) ==
ParameterExpression.Property(ParameterExpression.Constant(item), fieldName));
Während ich dies zum Kompilieren bringen kann, wird es nicht ganz so ausführen, wie es erforderlich ist.
Wie wäre es mit:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public Func<T, TRes> GetPropertyFunc<T, TRes>(string propertyName)
{
// get the propertyinfo of that property.
PropertyInfo propInfo = typeof(T).GetProperty(propertyName);
// reference the propertyinfo to get the value directly.
return (obj) => { return (TRes)propInfo.GetValue(obj, null); };
}
public void Run()
{
List<Person> personList = new List<Person>();
// fill with some data
personList.Add(new Person { Name = "John", Age = 45 });
personList.Add(new Person { Name = "Michael", Age = 31 });
personList.Add(new Person { Name = "Rose", Age = 63 });
// create a lookup functions (should be executed ones)
Func<Person, string> GetNameValue = GetPropertyFunc<Person, string>("Name");
Func<Person, int> GetAgeValue = GetPropertyFunc<Person, int>("Age");
// filter the list on name
IEnumerable<Person> filteredOnName = personList.Where(item => GetNameValue(item) == "Michael");
// filter the list on age > 35
IEnumerable<Person> filteredOnAge = personList.Where(item => GetAgeValue(item) > 35);
}
Dies ist eine Möglichkeit, Werte einer Eigenschaften durch Zeichenfolge ohne Verwendung dynamischer Abfragen zu erhalten. Der Nachteil ist, dass AL -Werte gepoppt/uneingeschränkt werden.