2009-10-06 50 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; 
    } 

可能有庫,更復雜的表達式(新對象創建等)。