2010-04-27 11 views
8

Sto provando a creare un'espressione lambda, contenente due assegnazioni (come mostrato più avanti), che posso quindi passare a un metodo Queryable.Select().Espressione lambda da utilizzare nella query Select()

Sto provando a passare una variabile stringa in un metodo e quindi a utilizzare tale variabile per creare l'espressione lambda in modo che possa essere utilizzata 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 vogliono per visualizzare nell'asse y del mio grafico, con l'asse x sempre corrispondente al DateTime. Pertanto, possono essenzialmente scegliere quali dati vengono confrontati con il valore DateTime (è un'app di tipo data warehouse).

ho, per esempio, una classe per memorizzare i dati recuperati in, e quindi utilizzare come fonte diagramma di:

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

ho (puramente sperimentalmente) costruito un albero di espressione per la clausola Dove usando il valore di stringa e che funziona bene:

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 })); 
    } 
} 

Tuttavia ...... ho provato un approccio simile per l'istruzione SELECT, ma proprio non riesco a farlo funzionare come ho bisogno del Select() per compilare sia X Valori Y della classe AnalysisChartSource, come questa:

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

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

risposta

15

Trovo che il modo migliore per capire come creare 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 il 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 Expression.MemberInit è quello che stai cercando.

+0

Jon ottima idea. Ti darei 100 voti per quella soluzione! :-) – gsharp

+0

Jon, geniale !! Mille grazie! Sono d'accordo con gsharp, una grande idea! - Reflector è il mio nuovo amico :-) Grazie ancora – jameschinnock

+0

@GSharp, ti aiuterò con questo: +1. – Steven