2010-04-27 17 views
8

Estoy tratando de construir una expresión lambda, que contenga dos asignaciones (como se muestra más abajo), que luego puedo pasar a un método Queryable.Select().Expresión Lambda para ser utilizada en la consulta Select()

Estoy tratando de pasar una variable de cadena a un método y luego usar esa variable para construir la expresión lambda para que pueda usarla en una consulta LINQ Select.

Mi razonamiento detrás de esto es que tengo un origen de datos de SQL Server con muchos nombres de columna, estoy creando una aplicación de gráficos que permitirá al usuario seleccionar, digamos escribiendo el nombre de la columna, la columna real de datos que desean para ver en el eje y de mi gráfico, con el eje x siempre siendo el DateTime. Por lo tanto, esencialmente pueden elegir qué datos grafican contra el valor de DateTime (es una aplicación de tipo depósito de datos).

He, por ejemplo, una clase para almacenar los datos recuperados en, y por lo tanto utilizar como la fuente gráfico de:

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

(puramente experimentalmente) he construido un árbol de expresión para la cláusula WHERE usando el valor de cadena y que funciona bien:

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

sin embargo ...... me han intentado un enfoque similar para la instrucción Select, pero simplemente no puede conseguir que funcione, ya que necesito Seleccionar() para llenar ambos X y Valores Y de la clase AnalysisChartSource, como este:

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

¿Cómo diablos puedo construir un árbol de expresión ... o ... posiblemente más al punto ... ¿hay una manera más fácil que me he perdido por completo?

Respuesta

15

Me parece que la mejor manera de averiguar cómo construir árboles de expresiones es ver lo que hace el compilador C#. Así que aquí hay un programa 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 }; 
    } 
} 

compilar ese, abra los resultados en el reflector y establecer la optimización de .NET 2.0. Se termina con el código generado para el método principal:

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

Básicamente, creo que Expression.MemberInit es lo que está buscando.

+0

Jon idea genial. ¡Te daría 100 votos para esa solución! :-) – gsharp

+0

Jon, genial !! ¡Muchas gracias de hecho! Estoy de acuerdo con gsharp, ¡una gran idea! - Reflector es mi nuevo amigo :-) Gracias de nuevo – jameschinnock

+0

@GSharp, te ayudaré con eso: +1. – Steven

Cuestiones relacionadas