2009-10-06 98 views
4

如何在不使用Compile()的情况下实现此功能,而仅使用普通反射?反思与编译获取MemberExpression的值

var value = Expression.Lambda(memberExpression).Compile().DynamicInvoke(); 

我希望这能够运行在IPhone(MonoTouch),它不允许动态编译。

更新:这里是更多的上下文。这是我的工作代码:

if (expression.Expression is ConstantExpression) 
{ 
var constantExpression = (ConstantExpression)expression.Expression; 
var fieldInfo = constantExpression.Value.GetType().GetField(expression.Member.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 
if (fieldInfo != null) 
{ 
    return fieldInfo.GetValue(constantExpression.Value); 
} 
{ 
    var propertyInfo = constantExpression.Value.GetType().GetProperty(expression.Member.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 
    if (propertyInfo != null) 
    { 
    return propertyInfo.GetValue(constantExpression.Value, null); 
    } 
} 
} 
else 
{ 
return Expression.Lambda(expression.Expression).Compile().DynamicInvoke(); 
} 

正如你所看到的,如果该块不使用运行时编译获得值的代码。我的目标是在else块而不是中的代码使用运行时编译。

回答

4

你不能。反射是元数据的工具,并且非常有限的字节码检测。它不允许突变或代码生成。从根本上说,你在这里试图实现的是元数据和IL生成行为。反射不适用于这种情况。

+0

你说的不完全正确。例如,我知道,在memberExpression.Expression是一个ConstantExpression的情况下,您可以通过反映常量表达式的Value属性来获取它的值。我的问题是,当它不是一个ConstantExpression,我不知道如何得到一个持有该值的实例的句柄。 – 2009-10-06 22:50:52

+0

如果它不是一个常量,你需要执行它才能得到结果。因此编译。 – Gregory 2009-10-08 02:19:53

0

我有一些更具体的情况:

private static object ExtractValue(Expression expression) 
    { 
     if (expression == null) 
     { 
      return null; 
     } 

     var ce = expression as ConstantExpression; 
     if (ce != null) 
     { 
      return ce.Value; 
     } 

     var ma = expression as MemberExpression; 
     if (ma != null) 
     { 
      var se = ma.Expression; 
      object val = null; 
      if (se != null) 
      { 
       val = ExtractValue(se); 
      } 

      var fi = ma.Member as FieldInfo; 
      if (fi != null) 
      { 
       return fi.GetValue(val); 
      } 
      else 
      { 
       var pi = ma.Member as PropertyInfo; 
       if (pi != null) 
       { 
        return pi.GetValue(val); 
       } 
      } 
     } 

     var mce = expression as MethodCallExpression; 
     if (mce != null) 
     { 
      return mce.Method.Invoke(ExtractValue(mce.Object), mce.Arguments.Select(ExtractValue).ToArray()); 
     } 

     var le = expression as LambdaExpression; 
     if (le != null) 
     { 
      if (le.Parameters.Count == 0) 
      { 
       return ExtractValue(le.Body); 
      } 
      else 
      { 
       return le.Compile().DynamicInvoke(); 
      } 
     } 

     var dynamicInvoke = Expression.Lambda(expression).Compile().DynamicInvoke(); 
     return dynamicInvoke; 
    } 

可能有库,更复杂的表达式(新对象创建等)。