2010-04-27 4 views
8

두 개의 배정 (아래 그림 참조)이 포함 된 람다 식을 작성하려고하며 Queryable.Select() 메서드에 전달할 수 있습니다.Select() 쿼리에서 사용되는 람다 식

문자열 변수를 메서드에 전달한 다음 해당 변수를 사용하여 LINQ 선택 쿼리에서 사용할 수 있도록 람다 식을 작성하려고합니다.

필자가 추론하는 이유는 많은 열 이름을 가진 SQL Server 데이터 소스를 가지고 있기 때문에 사용자가 원하는 열의 실제 열을 선택하여 열 이름을 선택하는 차트 작성 응용 프로그램을 만드는 것입니다. 내 차트의 y 축에서 볼 수 있으며 x 축은 항상 DateTime입니다. 따라서 DateTime 값 (데이터웨어 하우스 유형 앱)에 대해 차트로 어떤 데이터를 선택할 수 있습니다.

내가, 예를 들어, 따라서에서 검색된 데이터를 저장하고있는 클래스의 차트 소스로 사용했다 : 나는 (순수 experimentaly)를 사용하여 Where 절에 대한 식 트리를 구축

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

문자열 값이 잘 작동 : 그러나

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

모두 X를 채우기 위해) 내가 선택 문에 대한 유사한 접근 방식을 시도 ...하지만 내가 선택을 (필요에 따라 바로 작동하도록 얻을 수없고, 다음과 같이 AnalysisChartSource 클래스의 Y 값 :

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

지구상에서 어떻게 그런 식의 나무를 만들 수 있습니까? ... 또는 ... 요점을 더 잘 나타낼 수 있습니다 ... ... 내가 완전히 놓친 쉬운 방법이 있습니까?

답변

15

식 트리를 작성하는 가장 좋은 방법은 C# 컴파일러가 수행하는 작업을 확인하는 것입니다. 그래서 여기에 완벽한 프로그램이 있습니다 :

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

Reflector에서 결과를 열고 최적화를 .NET 2.0으로 설정하십시오. 당신은 메인 방법이 생성 된 코드와 끝까지 :

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

기본적으로, 나는 Expression.MemberInit이 필요하시면 생각합니다.

+0

존 좋은 생각. 그 해결책에 대해 100 표를 줄 것입니다! :-) – gsharp

+0

Jon, brilliant !! 참으로 많은 감사드립니다! 나는 좋은 생각 인 gsharp에 동의한다. - 리플렉터가 내 새 친구 :-) 다시 감사합니다. – jameschinnock

+0

@GSharp, 그걸로 당신을 도울 것입니다 : +1. – Steven