8

Is it possible to get a MethodInfo object from a method symbol?

So in the same vein as:

typeof(SomeClassSymbol) // this gets you a Type object

Here is what I want to do:

public class Meatwad
{
    MethodInfo method;

    public Meatwad()
    {
        method = ReflectionThingy.GetMethodInfo(SomeMethod);
    }

    public void SomeMethod() { }

}

How could I implement ReflectionThingy.GetMethodInfo? Given this is even possible at all, what about overloaded methods?

svick
  • 236,525
  • 50
  • 385
  • 514
Ronnie Overby
  • 45,287
  • 73
  • 267
  • 346
  • 2
    Somewhat related, I feel: [In Foof We Trust](http://blogs.msdn.com/b/ericlippert/archive/2009/05/21/in-foof-we-trust-a-dialogue.aspx) – Damien_The_Unbeliever Feb 27 '12 at 18:09
  • Eric Lippert's "In Foof We Trust: A Dialog" link is broken above. It is now https://learn.microsoft.com/en-us/archive/blogs/ericlippert/in-foof-we-trust-a-dialogue – John Doe Jan 27 '20 at 14:31
  • See also 'Poor man's Infoof' in comments at https://web.archive.org/web/20120329173717/http://blogs.msdn.com/b/ericlippert/archive/2009/05/21/in-foof-we-trust-a-dialogue.aspx – Mike Rosoft Jan 03 '23 at 11:50

2 Answers2

10

Delegates contain the MethodInfo you want in their Method property. So your helper method could be as simple as:

MethodInfo GetMethodInfo(Delegate d)
{
    return d.Method;
}

You cannot convert directly from a method group to Delegate. But you can use a cast for that. E.g.:

GetMethodInfo((Action)Console.WriteLine)

Be aware that this won't work if you try to mix it with something like usr's solution. For example

GetMethodInfo((Action)(() => Console.WriteLine()))

will return the MethodInfo for the generated anonymous method, not for Console.WriteLine().

svick
  • 236,525
  • 50
  • 385
  • 514
  • 2
    I like this the best so far, but what is interesting is that you can construct an action with only the method symbol and get the MethodInfo from the Method property of the Action. That's ultimately what I was trying to learn how to do. If I have some time I'll decompile Action to see what's going on. – Ronnie Overby Feb 27 '12 at 18:10
3

This is not possible in C# directly. But you can build this yourself:

    static MemberInfo MemberInfoCore(Expression body, ParameterExpression param)
    {
        if (body.NodeType == ExpressionType.MemberAccess)
        {
            var bodyMemberAccess = (MemberExpression)body;
            return bodyMemberAccess.Member;
        }
        else if (body.NodeType == ExpressionType.Call)
        {
            var bodyMemberAccess = (MethodCallExpression)body;
            return bodyMemberAccess.Method;
        }
        else throw new NotSupportedException();
    }

    public static MemberInfo MemberInfo<T1>(Expression<Func<T1>> memberSelectionExpression)
    {
        if (memberSelectionExpression == null) throw new ArgumentNullException("memberSelectionExpression");
        return MemberInfoCore(memberSelectionExpression.Body, null/*param*/);
    }

And use it like this:

var methName = MemberInfo(() => SomeMethod()).MethodName;

That will provide you compile-time safety. Performance will not be good though.

usr
  • 168,620
  • 35
  • 240
  • 369
  • Why does you method have a parameter that is never used? – svick Feb 27 '12 at 17:54
  • 1
    I copied this out of a helper class that has 200 LOC. I just wanted to give the gist of it. Please treat this as pseudo-code ;-) The idea, though, will fully work. – usr Feb 27 '12 at 17:55
  • 2
    @usr When performance becomes a problem, it is easily solved by using this to initialise static readonly objects, instead of calling your function every time. –  Feb 27 '12 at 18:07