получить methodinfo из ссылки на метод C#

мы можем использовать C# typeof ключевое слово, когда мы хотим получить экземпляр типа для указанного типа. Но что я могу использовать, если я хочу получить MethodInfo метода по его ссылке?

например у меня есть простое консольное приложение. Он содержит Program.Main метод. Я хочу получить MethodInfo используя что-то вроде methodinfoof(Program.Main). У меня есть эта проблема, потому что имена методов могут измениться, поэтому я не могу просто использовать Type.GetMethodInfo(string MethodName) для этого.

у меня есть около 10 000 способов, которые я хотел бы получить MethodInfo, поэтому добавление любых пользовательских атрибутов или чего-либо еще в мои методы не является решением.

6 ответов


небольшая адаптация ранее опубликованного ответа, но это сообщение в блоге, похоже, достигает того, что вы просите; http://blog.functionalfun.net/2009/10/getting-methodinfo-of-generic-method.html

использование образца было бы следующим образом;

var methodInfo = SymbolExtensions.GetMethodInfo(() => Program.Main());

первоначальный ответ был на этот вопрос;https://stackoverflow.com/a/9132588/5827


вы можете использовать деревья выражений для нестатических методов. Вот пример.

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

public static class MethodInfoHelper
{
    public static MethodInfo GetMethodInfo<T>(Expression<Action<T>> expression)
    {
        var member = expression.Body as MethodCallExpression;

        if (member != null)
            return member.Method;

        throw new ArgumentException("Expression is not a method", "expression");
    }
}

вы бы использовали его так:

        MethodInfo mi = MethodInfoHelper.GetMethodInfo<Program>(x => x.Test());
        Console.WriteLine(mi.Name);

Test () - функция-член, объявленная в классе программы.

использовать MemberExpression и MemberInfo вместо этого, если вы хотите поддерживать геттеры и сеттеры свойств.


тест класс

public class  Foo
{
    public void DoFoo()
    {
        Trace.WriteLine("DoFoo");
    }

    public static void DoStaticFoo()
    {
        Trace.WriteLine("DoStaticFoo");
    }
}

и вы можете сделать что-то подобное

MethodInfo GetMethodInfo(Action a)
{
    return a.Method;
}

var foo = new Foo();
MethodInfo mi = GetMethodInfo(foo.DoFoo);
MethodInfo miStatic = GetMethodInfo(Foo.DoStaticFoo);

//do whatever you need with method info

обновление
В комментарии @Greg если у вас есть некоторые параметры методов, вы можете использовать Action<T>, Action<T1, T2>, Action<T1, T2, T3> или Func<T1>, неудобство в том, что вам все равно нужно будет написать перегрузки для GetMethodInfo.


Я знаю, что это очень старый пост, но я просто выброшу это там для кого-то, кто все еще может искать простое решение для этого.. Просто кажется, что никто не подумал о простейшем решении:

typeof(Program).GetMethods();

возвращает массив с MethodInfo всех методов в классе программы, независимо от атрибутов или наличия параметров или нет.

вы можете повторить его, если хотите, например, перечислить имена всех ваших 10.000+ методы.

вы также можете сделать typeof(Program).GetMethod(nameof(Program.Main)); таким образом, если имя метода изменить рефакторинг Visual Studio переименует его здесь тоже.

Примечание: ключевое слово "nameof" не было доступно 5 лет назад, когда был опубликован вопрос.


Я создал шаблон T4, который создает необходимые вспомогательные функции, чтобы помочь вам в этом. Он создает список функций для получения объектов MethodInfo из методов Func или Action.

скопируйте следующий код в файл с именем GetMethodInfo.tt:

<#@ template language="C#" #>
<#@ output extension=".cs" encoding="utf-8" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Text" #>
using System;
using System.Linq.Expressions;
using System.Reflection;

namespace Tools
{
    public static class GetMethodInfo
    {
<# int max = 12;
for(int i = 0; i <= max; i++) 
{
    var builder = new StringBuilder();

    for(int j = 0; j <= i; j++) 
    {
        builder.Append("T");
        builder.Append(j);
        if(j != i) 
        {
            builder.Append(", ");
        }
    }

    var T = builder.ToString();
#>
        public static MethodInfo ForFunc<T, <#= T #>>(Expression<Func<T, <#= T #>>> expression)
        {
            var member = expression.Body as MethodCallExpression;

            if (member != null)
                return member.Method;

            throw new ArgumentException("Expression is not a method", "expression");
        }

        public static MethodInfo ForAction<<#= T #>>(Expression<Action<<#= T #>>> expression)
        {
            var member = expression.Body as MethodCallExpression;

            if (member != null)
                return member.Method;

            throw new ArgumentException("Expression is not a method", "expression");
        }

<# } #>
    }
}

Примечания:

  • пожалуйста, убедитесь, что Создать Действие of the .шаблон tt имеет значение нет
  • вы можете создать более или менее функции путем установки переменной max в соответствующую настройку.

может быть, не идеальный способ, но это может помочь:

var callback = typeof(BlogController).GetMethod(nameof(BlogController.GetBlogs));