反射与编译以获得 MemberExpression 的值

发布于 2024-08-07 02:09:57 字数 1046 浏览 3 评论 0原文

如何在不使用 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 块中的代码使用运行时编译。

How can I achieve this without using Compile() but just with normal reflection?

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

I want this to be able to run on an IPhone (MonoTouch), which does not allow dynamic compiling.

UPDATE: Here is more context. This is the code I am working on:

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

As you can see, the code in the if block uses no runtime compilation to obtain the value. My goal is that the code in the in the else block not use runtime compilation either.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

放赐 2024-08-14 02:09:57

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

You cannot. Reflection is tool for metadata and very limited byte code inspection. It does not allow for mutation or code generation. Fundamentally what you are trying to achieve here is a metadata and IL generation act. Reflection will not work for this scenario.

反话 2024-08-14 02:09:57

我有一些更具体的情况:

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

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

I have some more specific cases:

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

May be there are library with more complex expressions (new object creations etc.).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文