2009-05-24 113 views
2

更新:這並不工作,我太傻了:(參數問題

我有以下的擴展方法

public static string ExtMethod(this object self, object 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); 

什麼,我需要做的是評估「myparameter」,給予「expr「和」 T「,因爲兩種情況xmyparameter使用

,我想我需要創建形式的委託:

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

我認爲這會工作:

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

這是硬核......還是不明白是什麼問題。 :) – 2009-05-24 11:23:06

+0

對象的擴展方法很少是一個好主意;和(迂腐)你正在創建一個表達式樹(不是委託) - 但現在看... – 2009-05-24 11:36:20

+0

@Marc這只是僞代碼;) – 2009-05-24 11:43:43

回答

6

OK;到底了;在該行:

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

如果你並不想在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

如果你檢查expr.Parameters.Count,如果它是0,不調用的參數?