Clausola Where semplice in Expression Tree

c# expression-trees where

Domanda

Sto tentando di costruire una semplice clausola Where.

Questo è il codice che non funziona:

EDIT questo codice funziona bene ora (grazie alle risposte di seguito).

public class Item
{
    public int Value { get; set; }
    public string Name { get; set; }
}

var _List = new List<Item>
{
    new Item{ Name = "Smith", Value = 1},
    new Item{ Name = "Smith", Value = 2},
    new Item{ Name = "Wesson", Value = 3},
    new Item{ Name = "Wesson", Value = 4},
};

// Where(x => x.Value == 1)
var _Type = typeof(Item);
var _Prop = _Type.GetProperty("Value");
var _Param = Expression.Parameter(_Type, _Prop.Name);
var _Left = Expression.PropertyOrField(_Param, _Prop.Name);
var _Right = Expression.Constant(1, _Prop.PropertyType); 
var _Body = Expression.Equal(_Left, _Right);
var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param); 
var _Result = _List.AsQueryable().Where(_Where);

Grazie.

Risposta accettata

Ci sono diversi problemi con il tuo codice:

  1. È necessario passare 1 e non "1" per la costante intera 1 .

    var _Right = Expression.Constant(1, _Prop.PropertyType);
    
  2. Espressione.Equalizza se due alberi di espressione sono uguali. Restituisce un bool .

    Expression.Equal restituisce un albero di espressioni che rappresenta un controllo di uguaglianza.

    var _Body = Expression.Equal(_Left, _Right);
    
  3. Il parametro è di tipo Item e non int .

    var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param);
    
  4. L'elenco <T> implementa IEnumerable <T>, ma non IQueryable <T>.

    IEnumerable <T> funziona con i delegati, mentre IQueryable <T> funziona con gli alberi di espressione.

    Quindi è necessario compilare l'albero delle espressioni a un delegato

    var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param).Compile();
    var _Result = _List.Where(_Where);
    

    o converti l'elenco in IQueryable <T>.

    var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param);
    var _Result = _List.AsQueryable().Where(_Where);
    

Codice di lavoro:

// Where(x => x.Value == 1)
var _Param = Expression.Parameter(typeof(Item), "x");
var _Left = Expression.PropertyOrField(_Param, "Value");
var _Right = Expression.Constant(1);
var _Body = Expression.Equal(_Left, _Right);
var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param).Compile();
var _Result = _List.Where(_Where);


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché