2010-01-20 7 views
6

런타임에 람다 식을 사용하는 코드 부분이 있는데, 컴파일하고 호출 할 수 있습니다. 실행 시간을 절약하기 위해람다 식에서 매개 변수 바꾸기

Something thing; 

Expression<Action<Something>> expression = (c => c.DoWork()); 
Delegate del = expression.Compile(); 
del.DynamicInvoke(thing); 

, I는 캐시 키 람다 식 문자열 인 Dictionary<String, Delegate>를 컴파일 그 대리자가 저장된다.

정확하게 동일한 통화의 경우 정상적으로 작동합니다. 그러나 나는 "d => d.DoWork()"와 같은 lambdas를받을 수 있음을 깨달았는데, 실제로 같은 대리자를 사용해야했는데 그렇지 않았습니다.

람다 표현식의 요소를 대체하기 위해 깨끗한 방법 ("String.Replace를 사용하지 않음"으로 읽었습니다. 이미 읽었습니다)을 사용하면 궁금합니다. arg0

(c => c.DoWork())

(d => d.DoWork()) 형질 전환과 비교 람다에서 Expression.Parameter (유형 이름)에 주입 fuctionnally 유사한 것을 사용하여 (arg0 => arg0.DoWork())있다.

그럴 수 있습니까? (답변에는 C# 4.0이 포함될 수 있습니다.)

+0

키는 항상 (형식) arg => arg.Method() 또는 더 복잡한 형식이 필요합니까? – Elisha

+0

수신 된 람다는'(f, g) => f.Method (g)'와 같은 매개 변수를 더 많이 가질 수 있으며 f 및 g 유형을 갖게됩니다. 열쇠는 실제로 아주 평범하고 돌로 설정되어 있지 않습니다. ((T) arg0, (V) arg1) => arg0.Method (arg1)'와 같이 트릭을 할 수있는 두 개의 람다 사이의 동등성을 나타낼 수있는 적절한 방법입니다. 열쇠. –

답변

3

나를 위해 가장 쉬운 방법 이었기 때문에 문자열을 사용했습니다. 매개 변수 식의 이름을 수동으로 변경할 수는 없지만 ("Name"속성이 있지만 읽기 전용이므로) 조각으로 새 식을 구성해야합니다. 내가 한 것은 "이름이없는"매개 변수입니다 (실제로 Param_0이라는 자동 생성 된 이름을 얻습니다). 그런 다음 이전 매개 변수와 거의 같은 새 식을 만들지 만 새 매개 변수를 사용합니다.

public static void Main() 
{ 
    String thing = "test"; 

    Expression<Action<String>> expression = c => c.ToUpper(); 
    Delegate del = expression.Compile(); 
    del.DynamicInvoke(thing); 

    Dictionary<String, Delegate> cache = new Dictionary<String, Delegate>(); 
    cache.Add(GenerateKey(expression), del); 

    Expression<Action<String>> expression1 = d => d.ToUpper(); 
    var test = cache.ContainsKey(GenerateKey(expression1)); 
    Console.WriteLine(test); 

} 

public static string GenerateKey(Expression<Action<String>> expr) 
{ 
    ParameterExpression newParam = Expression.Parameter(expr.Parameters[0].Type); 
    Expression newExprBody = Expression.Call(newParam, ((MethodCallExpression)expr.Body).Method); 
    Expression<Action<String>> newExpr = Expression.Lambda<Action<String>>(newExprBody, newParam); 
    return newExpr.ToString(); 
} 
+0

결국 나는 비슷한 것으로 돌아갔습니다. 그러나 나는 여전히 λ 표현을 비교하는 더 대표적인 방법을 찾고 있습니다. –

+0

@Alexandra 동일한 Body 표현식을 사용하여 기존 MethodCallExpression에서 새로운 MethodCallExpression을 생성하려고합니다. 다른 형식의 인수를 사용합니다. GenerateKey 메서드와 비슷한 것을 사용하여이 작업을 수행 할 수 있습니까? 참조 : http://stackoverflow.com/questions/14363387/how-can-i-repurpose-a-generic-c-sharp-expression-allowing-the-input-type-argumen#comment19974655_14363387 –

3

텍스트보다 람다 표현식이 더 있습니다. 람다는 컴파일러에 의해 훨씬 더 복잡한 것으로 재 작성됩니다. 예를 들어 변수를 닫을 수 있습니다 (다른 대표를 포함 할 수 있음). 즉, 두 개의 람다가 완전히 똑같아 보이지만 완전히 다른 동작을 수행 할 수 있습니다.

컴파일 된 표현식을 캐싱해야 할 수도 있지만, 표현식의 텍스트보다 키에 대해 더 많은 숫자가 인 의미가 있습니다. 그렇지 않으면 인수 대체가 도움이되지 않습니다.

관련 문제