2013-02-18 2 views
3

참조 매개 변수가있는 메서드를 호출하는 식을 만드는 방법을 이해하려고합니다.표현식 트리를 사용하여 참조 변수가있는 메서드를 호출하는 방법

간단한 (그러나 인공적인) 예제로 제 질문을 설명해 드리겠습니다. 방법을 고려하십시오

public static int TwiceTheInput(int x) 
    { 
     return x*2; 
    } 

내가 좋아하는 뭔가를 수행하여 위의 메소드를 호출하는 식을 만들 수 있습니다 실행에

{ 
     var inputVar = Expression.Variable(typeof (int), "input"); 
     var blockExp = 
      Expression.Block(
        new[] {inputVar} 
        , Expression.Assign(inputVar, Expression.Constant(10)) 
        , Expression.Assign(inputVar, Expression.Call(GetType().GetMethod("TwiceTheInput", new[] { typeof(int) }), inputVar)) 
        , inputVar 
        ); 
     var result = Expression.Lambda<Func<int>>(blockExp).Compile()(); 
    } 

은 위의 "결과는"20의 가치와 끝까지해야한다. 지금 참조에 의한 매개 변수를 사용 TwiceTheInput()의 버전 고려 : 나는 TwiceTheInputByRef을 (전화 유사한 식 트리를 작성하려면 어떻게

public static void TwiceTheInputByRef(ref int x) 
    { 
     x = x * 2; 
    } 

를) 및 통과 인수에 대한 언급으로?

해결책 : (Thanks to Cicada). 사용

Type.MakeByRefType() 

여기 식 트리를 생성하는 코드 세그먼트의 :

 { 
     var inputVar = Expression.Variable(typeof(int), "input"); 
     var blockExp = 
      Expression.Block(
        new[] { inputVar } 
        , Expression.Assign(inputVar, Expression.Constant(10)) 
        , Expression.Call(GetType().GetMethod("TwiceTheInputByRef", new[] { typeof(int).MakeByRefType() }), inputVar) 
        , inputVar 
        ); 
     var result = Expression.Lambda<Func<int>>(blockExp).Compile()(); 
    } 
+2

람다 식을 사용하여 같은 방법을 호출하고 C# 컴파일러를 사용하여이를 표현식 트리로 변환 한 다음 decompiling 했습니까? 그게 보통 표현식 트리를 만드는 법을 배우는 것입니다. –

+0

아니요, 전에는 해본 적이 없습니다. 예를 통해 걷는 모든 URL? – DPrb

답변

3

당신은 많은 변화 단지 Assign를 제거하고 typeof(int).MakeByRefType()typeof(int)를 변경할 필요가 없습니다.

var blockExp = Expression.Block(
    new[] { inputVar } 
    , Expression.Assign(inputVar, Expression.Constant(10)) 
    , Expression.Call(
     typeof(Program).GetMethod( 
      "TwiceTheInputByRef", new [] { typeof(int).MakeByRefType() }), 
     inputVar) 
    , inputVar 
); 
+0

감사합니다. 그거야. – DPrb

+0

내 머리 부분을 기억하지 말고 여기에 반 __makeref 키워드를 사용할 수 있습니까? 자연스럽게 실제 변수가 필요합니다. – JerKimball

+0

@JerKimball 당신이 말했듯이,'__makeref'는 변수가 아닌 타입에서 작동하기 때문에 여기서는 사용할 수 없습니다. 'MakeByRefType' 부분은 단지'GetMethod'에 의해'TwiceTheInputByRef'의 적절한 오버로드를 해결하기 위해 사용됩니다 : 만약 과부하가 없다면, 그 두 번째 인자는 불필요합니다. –