Отражение против компиляции, чтобы получить значение MemberExpression - PullRequest
4 голосов
/ 06 октября 2009

Как мне этого добиться, не используя 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 ]

4 голосов
/ 06 октября 2009

Вы не можете. Reflection - это инструмент для метаданных и проверки очень ограниченного байтового кода. Он не допускает мутации или генерации кода. По сути, здесь вы пытаетесь достичь метаданных и акта генерации IL. Отражение не будет работать для этого сценария.

0 голосов
/ 31 октября 2013

У меня есть несколько более конкретных случаев:

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

Может быть, есть библиотека с более сложными выражениями (создание новых объектов и т. Д.).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...