Ich suche nach einer Möglichkeit, eine generische Methode mit einem Lambda-Ausdruck aufzurufen, der Contains in einem Array von Elementen aufruft.Reflection zum Aufrufen einer generischen Methode mit Lambda-Ausdrucksparameter
In diesem Fall verwende ich Entity Framework Where-Methode, aber das Szenario könnte in anderen IEnumerables angewendet werden.
Ich muss die letzte Zeile des obigen Codes durch Reflection aufrufen, damit ich jeden Typ und jede Eigenschaft verwenden kann, um die Contains-Methode zu übergeben.
var context = new TestEntities();
var items = new[] {100, 200, 400, 777}; //IN list (will be tested through Contains)
var type = typeof(MyType);
context.Set(type).Where(e => items.Contains(e.Id)); //**What is equivalent to this line using Reflection?**
In der Forschung habe ich bemerkt, dass ich GetMethod, Makegenerictype und Expression verwenden sollte, um das zu erreichen, aber ich kann nicht herausfinden, wie es zu tun. Es wäre sehr hilfreich, dieses Beispiel zu haben, damit ich nachvollziehen kann, wie Reflection mit Lambda und generischen Konzepten arbeitet.
Grundsätzlich ist das Ziel, eine korrekte Version einer Funktion wie folgt zu schreiben:
//Return all items from a IEnumerable(target) that has at least one matching Property(propertyName)
//with its value contained in a IEnumerable(possibleValues)
static IEnumerable GetFilteredList(IEnumerable target, string propertyName, IEnumerable searchValues)
{
return target.Where(t => searchValues.Contains(t.propertyName));
//Known the following:
//1) This function intentionally can't be compiled
//2) Where function can't be called directly from an untyped IEnumerable
//3) t is not actually recognized as a Type, so I can't access its property
//4) The property "propertyName" in t should be accessed via Linq.Expressions or Reflection
//5) Contains function can't be called directly from an untyped IEnumerable
}
//Testing environment
static void Main()
{
var listOfPerson = new List<Person> { new Person {Id = 3}, new Person {Id = 1}, new Person {Id = 5} };
var searchIds = new int[] { 1, 2, 3, 4 };
//Requirement: The function must not be generic like GetFilteredList<Person> or have the target parameter IEnumerable<Person>
//because the I need to pass different IEnumerable types, not known in compile-time
var searchResult = GetFilteredList(listOfPerson, "Id", searchIds);
foreach (var person in searchResult)
Console.Write(" Found {0}", ((Person) person).Id);
//Should output Found 3 Found 1
}
Ich bin nicht sicher, ob die anderen Fragen, die dieses Szenario befassen, weil ich mich eindeutig nicht denken konnte, zu verstehen, wie Ausdrücke funktionieren.
Update:
Ich kann nicht Generics benutzen, weil ich nur die Art und die Eigenschaft haben, getestet werden (in Enthält) zur Laufzeit. Nehmen Sie im ersten Codebeispiel an, dass "MyType" zur Kompilierungszeit nicht bekannt ist. Im zweiten Codebeispiel könnte der Typ als Parameter an die GetFilteredList-Funktion übergeben werden oder über Reflection (GetGenericArguments) abgerufen werden.
Danke,
Nur zur Erinnerung, eine Verbesserung könnte eine Möglichkeit sein, Invoke anstelle von DynamicInvoke in der return-Anweisung aufzurufen. – natenho
Sie sind ein Held! :) – AmmarCSE
2 Jahre später, immer noch das beste Beispiel für die Erstellung dynamischer Ausdrücke Ich habe hinzugefügt, dass es viel schneller ist, wenn Sie den Typ zu "IQueryable" statt "IEnumerable" ändern, da die Abfrage nicht erzwungen wird sofort auf der Client-Seite auszuführen und stattdessen an die Datenquelle weitergegeben wird (z. B. vom SQL-Server ausgeführt, wenn Sie Linq-to-SQL verwenden) –