Search code examples
c#reflectionfieldinfomemberinfo

How to get the MethodInfo of a function of a class, without string comparison


Similar to a previous question of mine, when I was asking about getting the FieldInfo of a field, How to get the FieldInfo of a field from the value, from the answers there, I compiled this helper class,

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

Which works perfectly well using the GetMemberInfo(this, c => c.myInt, but the commented out line is what I'm confused about now, GetMemberInfo(this, c => c.testFunction) or GetMemberInfo(this, c => c.testFunction()).

Is there any way, without string comparison, I can get the member info that's available from a GetMethods() runthrough, or GetMethod("testFunction")?


Solution

  • MemberExpression is only for properties and fields. You probably look at MethodCallExpression.

    So something like

    ((MethodCallExpression)expr.Body).Method
    

    assuming that you pass a lambda that looks like () => this.testFunction()

    So to get the MemberInfo you would get a Method property of a MemberCallExpression.

    Also, you should then change the GetMemberInfo method signature, because this is a lambda that takes no parameters and returns the same type that your method returns, so it will be a private MemberInfo GetMemberInfo<T>(Expression<Func<T, void>> expr) or something close to it.

    I'm not 100% sure, but what happens is, this.testFunction is actually a syntactic sugar for delegate creation, so it's actually something like new Action(this.testFunction) assuming testFunction is void testFunction(). Or something like this, because this.testFunction is not a member access, but rather a delegate creation.