【问题标题】:How to get the MethodInfo of a function of a class, without string comparison如何在没有字符串比较的情况下获取类的函数的MethodInfo
【发布时间】:2015-03-11 12:22:21
【问题描述】:

与我的上一个问题类似,当我询问从那里的答案中获取字段的 FieldInfo How to get the FieldInfo of a field from the value 时,我编译了这个帮助程序类,

using System;
using System.Reflection;
using System.Linq.Expressions;

internal class Program
{
    class MyClass
    {
#pragma warning disable 0414, 0612, 0618, 0649
        private int myInt = 24;
#pragma warning restore 0414, 0612, 0618, 0649

        public const BindingFlags _flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

        public MyClass()
        {
            MemberInfo myIntMI = GetMemberInfo(this, c => c.myInt);
            Console.WriteLine(myIntMI.Name + ": " + GetFieldValue(myIntMI) + ", " + GetFieldInfo(myIntMI).FieldType);

//          MemberInfo tfMI = GetMemberInfo(this, cw => cw.testFunction());
//          MemberInfo tfMI = GetMemberInfo(this, cw => cw.testFunction);
//          Console.WriteLine(tfMI.Name + ": " + GetFieldValue(tfMI) + ", " + GetFieldInfo(tfMI).FieldType);

            foreach( var mi in GetType().GetMethods(_flags) )
            {
                Console.WriteLine("method: " + mi);
            }
        }

        private void testFunction() { }

        private object GetFieldValue(MemberInfo mi)
        {
            return GetFieldInfo(mi).GetValue(this);
        }

        private FieldInfo GetFieldInfo(MemberInfo mi)
        {
            return GetType().GetField(mi.Name, _flags);
        }

        private MemberInfo GetMemberInfo<TModel, TItem>(TModel model, Expression<Func<TModel, TItem>> expr)
        {
            return ( (MemberExpression)expr.Body ).Member;
        }
    }
}

使用GetMemberInfo(this, c =&gt; c.myInt 效果很好,但注释掉的行是我现在感到困惑的地方,GetMemberInfo(this, c =&gt; c.testFunction)GetMemberInfo(this, c =&gt; c.testFunction())

有没有什么方法可以在不进行字符串比较的情况下,从GetMethods()GetMethod("testFunction") 中获取成员信息?

【问题讨论】:

  • 我认为(但无法验证)为了能够将c =&gt; c.testFunction() 传递给GetMemberInfo,第二个参数的类型必须是Expression&lt;Action&lt;TModel&gt;&gt;。为了能够传递c =&gt; c.testFunction,我认为您的参数必须是Expression&lt;Func&lt;TModel, Action&gt;&gt; 类型。由于testFunction 没有返回类型,TItem 不会起作用。

标签: c# reflection fieldinfo memberinfo


【解决方案1】:

MemberExpression 仅适用于属性和字段。你可能看MethodCallExpression

类似

((MethodCallExpression)expr.Body).Method

假设您传递的 lambda 类似于 () =&gt; this.testFunction()

所以要获得MemberInfo,您将获得MemberCallExpressionMethod 属性。

此外,您应该更改 GetMemberInfo 方法签名,因为这是一个不带参数的 lambda,并且返回的类型与您的方法返回的类型相同,因此它将是 private MemberInfo GetMemberInfo&lt;T&gt;(Expression&lt;Func&lt;T, void&gt;&gt; expr) 或接近它的东西。

我不能 100% 确定,但实际情况是,this.testFunction 实际上是用于创建委托的语法糖,所以它实际上类似于 new Action(this.testFunction),假设 testFunctionvoid testFunction()。或者类似的东西,因为this.testFunction 不是成员访问,而是委托创建。

【讨论】:

  • 返回类型为void 的方法不应该是Action 而不是Func&lt;T, void&gt;
  • 但是他可以尝试将这段代码用于可以接受参数和返回值的方法。 Lambda 本身肯定没有参数,但它仍然有被调用方法的返回类型。
  • 完美。当我意识到我想要/需要 MethodInfo 而不是 MemberInfo 时,我重新编辑了我的问题,但你的答案仍然是正确的(几乎)。我使用的是private MethodInfo GetMethodInfo(Expression&lt;Action&gt; expr) { return ( (MethodCallExpression)expr.Body ).Method; },这是您的答案,以及安的建议。非常感谢!
  • 没问题。由于某种原因,表达式的文档记录不是很好,很容易迷失方向
  • 我对 C# 领域的大量反射有这样的看法,如果你跳上 IRC 或类似的东西,我发现你会因为想做那种事情而受到打击.使用 Python,文档会更好,社区对这种类型的编码也更加开放。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-20
  • 2021-02-09
  • 1970-01-01
  • 1970-01-01
  • 2017-09-20
相关资源
最近更新 更多