反思与编译获取MemberExpression的价值

时间:2009-10-06 18:48:15

标签: c# reflection lambda

如何在不使用Compile()的情况下实现这一目标,但只能使用正常反射?

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();
}

如您所见,if块中的代码不使用运行时编译来获取值。我的目标是使用else块而不是中的代码使用运行时编译。

2 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分: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;
    }

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