Wie erstelle ich einen Linq-Ausdrucksbaum, der mit einem generischen Objekt verglichen wird?

c# entity-framework expression-trees generics linq

Frage

Ich habe ein IQueryable und ein Objekt vom Typ T.

Ich möchte IQueryable () ausführen, wobei (o => o.GetProperty (fieldName) == objectOfTypeT.GetProperty (fieldName))

damit ...

public IQueryable<T> DoWork<T>(string fieldName)
        where T : EntityObject
{
   ...
   T objectOfTypeT = ...;
   ....
   return SomeIQueryable<T>().Where(o => o.GetProperty(fieldName) == objectOfTypeT.GetProperty(fieldName));
}

Fyi, GetProperty ist keine gültige Funktion. Ich brauche etwas, das diese Funktion erfüllt.

Fühle ich am Freitag Nachmittag ein Gehirnschmelzen oder ist das eine komplexe Sache?


objectOfTypeT Ich kann Folgendes tun ...

public IQueryable<T> DoWork<T>(string fieldName)
        where T : EntityObject
{
   ...
   T objectOfTypeT = ...;
   ....
   return SomeIQueryable<T>().Where(o => o.GetProperty(fieldName) == objectOfTypeT.GetProperty(fieldName));
}

Was perfekt funktioniert, jetzt brauche ich nur den zweiten Teil:

SomeIQueryable () zurückgeben Wo (o => o.GetProperty (fieldName) == matchValue);

Akzeptierte Antwort

Wie 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 , die eine Reihe von Expressions Themen abdecken wird, hier .

Wenn Sie irgendwelche Probleme haben, ist eine andere Option, den Wert von objectOfTypeT zuerst zu extrahieren (mit Reflektion) und dann diesen Wert in der Expression.Constant , aber ich vermute, dass es in Ordnung ist "wie es ist".


Beliebte Antwort

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, um Werte von Eigenschaften per String abzurufen, ohne dynamische Abfragen zu verwenden. Der Nachteil ist, dass alle Werte Boxed / Unboxed sind.




Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum