2012-02-21 4 views
12

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

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

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

+1

Заканчивать ответ, который я отвечал на этот предыдущий вопрос; http://stackoverflow.com/a/9132588/5827 Это может помочь вам с тем, чего вы пытаетесь достичь. –

+0

@ChrisMcAtackney Вы можете разместить это в качестве ответа, ссылка имеет жизнеспособное решение. – dasblinkenlight

+4

См. Также Эрик Липперт «В Foof We Trust: The Dialogue» на http://blogs.msdn.com/b/ericlippert/archive/2009/05/21/in-foof-we-trust-a-dialogue.aspx – phoog

ответ

13

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

Пример использования будет следующим:

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

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

+0

@Jason: У него есть перегрузка без параметров. –

+2

@ Джейсон: Ты потерял меня - в чем ты смысл? Код, указанный выше *, * работает, и дает именно то, что задал оригинальный вопрос. МетодInfo.Main. Если вы хотите, чтобы MethodInfo для перегрузки имел параметр string [], тогда вызывайте его так: SymbolExtensions.GetMethodInfo (() => Program.Main (null); –

+0

Помните, что этот подход имеет угловой регистр (см. Http://stackoverflow.com/questions/6658669/lambda-expression-not-returning-expected-memberinfo) Во-вторых, лучше проверить унарные выражения, как в случае коробочных преобразований, таких как '() => IntMethod()'. – nawfal

4

Тест класс

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 

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

+0

@Jason - Вы можете заставить это работать с любым количеством параметров. Вместо 'Action' использовать' Action ',' Action ',' Action 'или' Func '... – Greg

+0

@Jason это ** работает ** для «Program.Main», см. обновление для статической версии. Он также работает, если метод не является «действием», так как вы можете видеть, что метод возвращает void. Но для того, чтобы использовать такую ​​конструкцию, метод должен быть передан как «Действие». Это отвечает на вопрос OP о том, как получить информацию об методе – oleksii

+0

@ Джейсон, я получил вас, ваше беспокойство о 'parameters', а не' static'. – oleksii

8

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

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() является функцией члена, объявленного в классе Program.

Использовать MemberExpression и MemberInfo вместо этого, если вы хотите поддерживать имущественные получатели и сеттеры.

+1

Только если у метода нет параметров, это сработает. – jason

+3

Просто введите значения нуля или значения по умолчанию вместо параметров. –

+0

Любой способ заставить это работать на статический метод в статическом классе? – oscilatingcretin

1

Я создал шаблон 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"); 
     } 

<# } #> 
    } 
} 

Примечания:

  • пожалуйста, убедитесь, что Build Action из.tt установлен в Нет
  • вы можете создать более или менее функции, установив максимальную переменную в соответствующую настройку.
3

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

typeof(Program).GetMethods(); 

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

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

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

ПРИМЕЧАНИЕ. Ключевое слово «nameof» было недоступно 5 лет назад, когда был отправлен вопрос.

0

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

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