2009-05-24 65 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,不调用的参数?