2015-03-11 7 views
3

Как и предыдущий вопрос, когда я спрашивал о получении поля FieldInfo поля How to get the FieldInfo of a field from the value, из ответов там я скомпилировал этот вспомогательный класс ,Как получить MethodInfo функции класса без сравнения строк

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 => c.myInt, но закомментирована линия это то, что я не совсем понимаю сейчас, GetMemberInfo(this, c => c.testFunction) или GetMemberInfo(this, c => c.testFunction()).

Есть ли какой-либо способ, без сравнения строк, я могу получить информацию о члене, доступную из прогона GetMethods(), или GetMethod("testFunction")?

+0

Я думаю (но не в состоянии проверить), что для того, чтобы передать 'c => c.testFunction()' в 'GetMemberInfo', тип второго параметра должен был бы быть« Expression > '. Чтобы иметь возможность передать 'c => c.testFunction', я * думаю * ваш параметр должен быть типа' Expression > '. Поскольку 'testFunction' не имеет типа возврата,' TItem' не будет играть роли. –

ответ

2

MemberExpression только для свойств и полей. Вероятно, вы посмотрите на MethodCallExpression.

Так что-то вроде

((MethodCallExpression)expr.Body).Method 

при условии, что вы передаете лямбда, который выглядит как () => this.testFunction()

Так, чтобы получить MemberInfo вы получите Method свойство MemberCallExpression.

Кроме того, вы должны затем изменить подпись метода GetMemberInfo, потому что это лямбда, которая не принимает никаких параметров и возвращает тот же тип, что и ваш метод, поэтому он будет private MemberInfo GetMemberInfo<T>(Expression<Func<T, void>> expr) или что-то рядом с ним.

Я не уверен на 100%, но то, что происходит это, this.testFunction на самом деле является синтаксическим сахаром для создания делегата, так что это на самом деле что-то вроде new Action(this.testFunction) предполагающей testFunction является void testFunction(). Или что-то вроде этого, потому что this.testFunction - это не членский доступ, а создание делегата.

+1

Не должен ли метод с типом возврата 'void' быть' Action', а не 'Func '? –

+1

Но он может попытаться использовать этот код для методов, которые могут принимать параметры и возвращать значения. У самой Lambda наверняка не будет никаких параметров, но у нее все равно будет тип возвращаемого метода. – Spo1ler

+0

Отлично. Я повторно отредактировал свой вопрос, когда понял, что мне нужен/нужен MethodInfo, а не MemberInfo, но ваш ответ по-прежнему верен (почти). То, что я использовал, является 'private MethodInfo GetMethodInfo (выражение expr) {return ((MethodCallExpression) expr.Body). Метод; } ', который является вашим ответом, вместе с предложением Энн. Большое спасибо! – seaders