Espressione lambda da utilizzare nella query Select ()

c# expression-trees lambda

Domanda

Sto cercando di creare un'espressione lambda, contenente due assegnazioni (come mostrato più avanti), che posso quindi passare a un metodo Queryable.Select ().

Sto cercando di passare una variabile stringa in un metodo e quindi di usare quella variabile per creare l'espressione lambda in modo che possa usarla in una query LINQ Select.

Il mio ragionamento dietro è che ho un'origine dati di SQL Server con molti nomi di colonne, sto creando un'applicazione di creazione di grafici che consentirà all'utente di selezionare, ad esempio digitando il nome della colonna, la colonna effettiva di dati che si desidera visualizzare nel asse y del mio grafico, con l'asse x sempre come data. Pertanto, possono essenzialmente scegliere quali dati vengono confrontati con il valore DateTime (è un'app di tipo data warehouse).

Ho, ad esempio, una classe per archiviare i dati recuperati, e quindi utilizzare come fonte di grafici di:

public class AnalysisChartSource
{
    public DateTime Invoicedate { get; set; }
    public Decimal yValue { get; set; }
}

Ho (puramente sperimentale) costruito un albero di espressioni per la clausola Where che utilizza il valore String e che funziona correttamente:

public void GetData(String yAxis)
{
    using (DataClasses1DataContext db = new DataClasses1DataContext())
    {
        var data = this.FunctionOne().AsQueryable<AnalysisChartSource>();
        //just to get some temp data in....

        ParameterExpression pe = Expression.Parameter(typeof(AnalysisChartSource), "p");
        Expression left = Expression.MakeMemberAccess(pe,
                                                typeof(AnalysisChartSource).GetProperty(yAxis));
        Expression right = Expression.Constant((Decimal)16);
        Expression e2 = Expression.LessThan(left, right);
        Expression expNew = Expression.New(typeof(AnalysisChartSource));

        LambdaExpression le = Expression.Lambda(left, pe);

        MethodCallExpression whereCall = Expression.Call(
            typeof(Queryable), "Where", new Type[] { data.ElementType },
            data.Expression,
            Expression.Lambda<Func<AnalysisChartSource, bool>>(e2, new ParameterExpression[] { pe }));
    }
}

Comunque ... »Ho provato un approccio simile per l'istruzione Select, ma non riesco a farlo funzionare perché ho bisogno del Select () per popolare i valori X e Y della classe AnalysisChartSource, in questo modo:

.Select(c => new AnalysisChartSource 
{ Invoicedate = c.Invoicedate, yValue = c.yValue}).AsEnumerable();

Come diavolo posso costruire un albero di espressione del genere ... o ... a volte più al punto ... c'è un modo più semplice che mi è sfuggito del tutto?

Risposta accettata

Trovo che il modo migliore per capire come costruire alberi di espressioni è vedere cosa fa il compilatore C #. Quindi ecco un programma completo:

using System;
using System.Linq.Expressions;

public class Foo
{
    public int X { get; set; }
    public int Y { get; set; }
}

class Test
{
    static void Main()
    {
        Expression<Func<int, Foo>> builder = 
            z => new Foo { X = z, Y = z };
    }
}

Compilatelo, aprite i risultati in Reflector e impostate l'ottimizzazione su .NET 2.0. Si finisce con questo codice generato per il metodo Main:

ParameterExpression expression2;
Expression<Func<int, Foo>> expression = 
  Expression.Lambda<Func<int, Foo>>(
    Expression.MemberInit(
      Expression.New((ConstructorInfo) methodof(Foo..ctor), new Expression[0]),
      new MemberBinding[] { Expression.Bind((MethodInfo) methodof(Foo.set_X),
                           expression2 = Expression.Parameter(typeof(int), "z")),
                           Expression.Bind((MethodInfo) methodof(Foo.set_Y), 
                                            expression2) }
    ),
    new ParameterExpression[] { expression2 });

Fondamentalmente, penso che Expression.MemberInit è ciò che stai cercando.



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é