2010-08-24 60 views
1

给出下面的变量之一,如何'检查'它们以获取传入的参数值?即12345在lambda /表达式树内寻找

System.Func<DateTime> f1 =() => DateTime.Now.AddDays(12345); 

System.Linq.Expressions.Expression<System.Func<DateTime>> 
         f2 =() => DateTime.Now.AddDays(12345); 

编辑:

下面的两个答案通过的Mikael和柯克都回答我的问题,一部开拓创新。 但是,现在我已经使这个更复杂一点来处理“现实生活”了。 理想我正在寻找一个“一般”的解决方案,这将有一些工作alongs的下面几行:

var days = 123; 
var hours = 456; 
System.Func<DateTime> f1 =() => DateTime.Now.AddDays(days).AddHours(hours); 
Expression<System.Func<DateTime>> f2 =() => DateTime.Now.AddDays(days).AddHours(hours); 

我真正追求的是产生unikey办法“钥匙”给予了lamda表达。 我的想法是使用方法名称和参数名称/值对,但我欢迎其他建议!谢谢。

+0

'f1'确实包含的信息,但只有通过检查从C#编译器生成的IL。如果执行了'f2',则在运行时编译并且C#编译器只创建一个表达式树,您可以使用'Expression'类型和子类型来检查。 – Richard 2010-08-24 15:40:53

回答

2

如果您的意思是值12345,则该数据仅在f2中可用。对于F2:

MethodCallExpression call = (MethodCallExpression)f2.Body; 
ConstantExpression arg = (ConstantExpression)call.Arguments[0]; 
Console.WriteLine(arg.Value); 
1

我可以看到从F1获得它的唯一方法是:

int days = (f1() - DateTime.Now).Days; 

我怀疑是你想要的。

但是,如果函数的主体与您的示例一样清晰地定义,那么从f2获取值是可能的,而且并不困难。它会开始像((f2 as LambdaExpression).Body as MethodCallExpression)....

我可能需要很长时间才能找出确切的过程,但它可能会更容易,因为您只需在调试器中检查f2即可。

3

作为除了柯克沃尔的答案,如果你想拥有12345作为一个对象,你可以使用以下命令:

public void Run() 
    { 
     System.Linq.Expressions.Expression<System.Func<DateTime>> f2 =() => DateTime.Now.AddDays(12345); 

     MethodCallExpression call = (MethodCallExpression)f2.Body; 
     ConstantExpression arg = (ConstantExpression)call.Arguments[0]; 

     var value = GetValue(arg); 
     Debug.WriteLine(value); 
    } 

    private object GetValue(ConstantExpression expression) 
    { 
     Expression conversion = Expression.Convert(expression, typeof(object)); 
     var getterLambda = Expression.Lambda<Func<object>>(conversion); 

     var getter = getterLambda.Compile(); 

     return getter(); 
    }