2009-05-24 6 views
2

업데이트 :이하지 내가이 어떤 수의 실행시에 다음과 같은 확장 방법매개 변수 문제

public static string ExtMethod(this object self, object myparameter); 

라고 한

:(일, 내가 당하고 바보 주어진

내가 " myparameter"를 평가한다 무엇을해야하는지
Expression<Func<T, string>> expr = x => x.property.ExtMethod(5); 
Expression<Func<T, string>> expr = x => x.property.ExtMethod(new object()); 
Expression<Func<T, string>> expr = x => x.property.ExtMethod(someMethod()); 
Expression<Func<T, string>> expr = x => x.property.ExtMethod(x.someMethod()); 
Expression<Func<T, string>> expr = x => x.property.ExtMethod(x.OtherProperty); 

, ": 가지의 방법, 나는이 모든 가능성을 생각한다

Expression<Func<T, object>> expr = x => [myparameter expression here] 

내가이 일 것이라고 생각 :

"하고는" T는 "때문에 xmyparameter에 사용되는 두 경우의

, 난 내가 형식의 대리자를 만드는 데 필요한 생각

var extMethodExpr = expr.Body as MethodCallExpression; 
var myparameterExpr = extMethodExpr.Arguments[1]; 

var myparam = Expression.Lambda(myparameterExpr, expr.Parameters).Compile().Invoke(someT) 

하지만 x 포함하지 않는 표현식 , 은 내가 TargetParameterCountException :(

를 얻을 수 내가 할 경우 이러한 경우

는 :

var myparam = Expression.Lambda(myparameterExpr).Compile().Invoke(someT) 

그것을 잘 작동합니다.

어떻게 해결할 수 있습니까?

감사

+0

이것은 하드 코어입니다 ... 여전히 문제가 무엇인지 이해할 수 없습니다. :) –

+0

개체에 대한 확장 메서드는 거의 좋은 아이디어가 아닙니다. 와 표현 트리 (대리인 아님)를 만드는 (보행자) - 그러나 지금보고 ... –

+0

@Marc 이것은 단지 의사 코드입니다.) –

답변

6

OK; 그것의 바닥에 도착했다; 라인에 : 당신이 someT 전달을 시도되지 않은 경우

var myparam = Expression.Lambda(myparameterExpr).Compile().Invoke(someT); 

, 이것은 인수에 x을 포함하지 않는 표현을 위해 일 것이다; 여기의 인스턴스를 주어 내부 매개 변수를 (평가 일부 작업 코드는

var myparam = Expression.Lambda(myparameterExpr, 
      outerLambda.Parameters[0]).Compile().Invoke(someT); 

: 간단하여 - 않는 사람들을 위해, 당신은 매개 변수 (원래의 람다에서 같은 일을) 포함하는 람다를 알려줄 필요 인수 유형); 이 포함되지 않은 경우에도 x과 관련된 매개 변수를 사용합니다. 그렇지 않은 경우 인스턴스와 어떤 관련이 있습니까?

using System; 
using System.Linq.Expressions; 
using System.Reflection; 
class Foo { 
    public string Bar {get;set;} 
    public int someMethod() { return 4; } 
    public int OtherProperty { get { return 3; } } 
} 
static class Program 
{ 
    static int someMethod() { return 3; } 
    static void Main() 
    { 
     Foo foo = new Foo(); 
     Test<Foo>(x => x.Bar.ExtMethod(5), foo); 
     Test<Foo>(x => x.Bar.ExtMethod(new object()), foo); 
     Test<Foo>(x => x.Bar.ExtMethod(someMethod()), foo); 
     Test<Foo>(x => x.Bar.ExtMethod(x.someMethod()), foo); 
     Test<Foo>(x => x.Bar.ExtMethod(x.OtherProperty), foo); 
    } 
    static void Test<T>(Expression<Func<T, string>> expr, T instance) 
    { 
     if (expr.Body.NodeType != ExpressionType.Call) 
     { 
      throw new InvalidOperationException("Call expected"); 
     } 
     var call = ((MethodCallExpression)expr.Body); 
     if (call.Method != typeof(Program).GetMethod(
      "ExtMethod", BindingFlags.Static | BindingFlags.NonPublic)) 
     { 
      throw new InvalidOperationException("ExtMethod expected"); 
     } 
     // we know that ExtMethod has 2 args; pick myParameter (the 2nd); 
     // then build an expression over arg, re-using our outer param 
     var newLambda = Expression.Lambda<Func<T, object>>(
      call.Arguments[1], expr.Parameters[0]); 

     // evaluate it and show the argument value 
     object value = newLambda.Compile()(instance); 
     Console.WriteLine(value); 
    } 
    static string ExtMethod(this object self, object myParameter) { 
     return self.ToString(); 
    } 
} 
+0

좋아, 나는 완전한 바보 야. 위의 코드는 작동합니다. 내 실제 코드에서 나는 T를 lambda.invoke()에 전달하지 않았으므로 TargetParameterCountException을 전달했다. 도! –

+0

+1과 + 당신의 노력에 대한 답변을 주셔서 감사합니다 :) 내가 버그를 찾는 데 도움이! –

0

당신이 expr.Parameters.Count을 확인하고이 0 인 경우, 매개 변수없이 호출하면?

+0

필자는 .Parameters가없는 Expression 만 expr로 사용합니다.이것을 우아하게 어떻게 접근 할 수 있습니까? –