2009-02-06 2 views
23

Я делаю некоторый анализ типа во время выполнения с использованием Reflection. Если у меня есть экземпляр MethodInfo, , как я могу выяснить, является ли это «реальным» методом или является методом getter/setter свойства? И если это свойство, как я могу найти его хостинг PropertyInfo обратно?Поиск хостинга PropertyInfo из MethodInfo из getter/setter

ответ

7

Ecma 335 указывает (но не требует), чтобы компиляторы использовали префиксы get_/set_ (глава 22.28). Я не знаю ни одного языка, который нарушает эту рекомендацию. Что делает его легко:

public static PropertyInfo GetPropFromMethod(Type t, MethodInfo method) { 
    if (!method.IsSpecialName) return null; 
    return t.GetProperty(method.Name.Substring(4), 
    BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); 
} 
+2

Из информационного текста требуется, чтобы он соответствовал требованиям CLS, но не требовался, чтобы быть действительным IL. –

+1

Я бы не рекомендовал идти этим путем. Я рекомендую проверить все свойства. Контур шаблона строк - не устойчивый. –

+1

Хотелось бы увидеть встречный пример. –

17

Ну, метод за геттером и сеттером : «реальные» методы.

Отслеживание возврата к свойству - шаблон (return vs take 1 arg) поможет сузить его - но вам нужно будет вызвать GetGetMethod/GetSetMethod для каждого, чтобы найти свойство.

Возможно возможно попробуйте Name (за исключением получения __/set__) - но это кажется хрупким. Вот длинная версия (без использования Name):

static PropertyInfo GetProperty(MethodInfo method) 
{ 
    bool takesArg = method.GetParameters().Length == 1; 
    bool hasReturn = method.ReturnType != typeof(void); 
    if (takesArg == hasReturn) return null; 
    if (takesArg) 
    { 
     return method.DeclaringType.GetProperties() 
      .Where(prop => prop.GetSetMethod() == method).FirstOrDefault(); 
    } 
    else 
    { 
     return method.DeclaringType.GetProperties() 
      .Where(prop => prop.GetGetMethod() == method).FirstOrDefault(); 
    } 
} 
+0

+1 для обходного пути, по-прежнему предпочитают имя .StartsWith ("get_"/"set_") '. – arul

+0

hmm ... возможно, для кода C#, по крайней мере ... они упомянуты в 17.2.7.1 ECMA 335 - но применимо ли это к другим языкам? Я проверю ECMA 334 ... –

+0

Уверен, что это, проверьте раздел 17.2.7.1. Для свойства P типа T зарезервированы следующие подписи: T get_P(); void set_P (значение T); Обе подписи зарезервированы, даже если свойство доступно только для чтения или только для записи. – arul

5

Посмотрите на MethodBase.IsSpecialName. Эти флаги используют методы, которые не должны быть явно видимыми, например, аксессоры свойств, методы подписки на события и перегрузки операторов.

Насколько я знаю, нет способа найти PropertyInfo без повторного использования свойств и сравнения методов.

+0

Согласно MS, вы не можете гарантировать, что будет установлен флаг IsSpecialName: http://connect.microsoft.com/VisualStudio/feedback/details/108302/for-property-accessors-get-set-isspecialname-false –

+0

IsSpecialName действительно работает. Я надеюсь, что это нечто изменило MS, потому что лучше иметь возможность проверять флаг, а не объяснять, какие языковые функции реализованы как (возможно, немаркированные) специальные методы. –

5

Я бы очень хотел, чтобы оставить это в качестве комментария, но я не могу, так как мое повторение не достаточно высокого :(

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

[Pure] 
    public static PropertyInfo GetParentProperty(this MethodInfo method) 
    { 
     if (method == null) throw new ArgumentNullException("method"); 
     var takesArg = method.GetParameters().Length == 1; 
     var hasReturn = method.ReturnType != typeof(void); 
     if (!(takesArg || hasReturn)) return null; 

     if (takesArg && !hasReturn) 
     { 
      return method.DeclaringType.GetProperties().FirstOrDefault(prop => prop.GetSetMethod() == method); 
     } 
     else 
     { 
      return method.DeclaringType.GetProperties().FirstOrDefault(prop => prop.GetGetMethod() == method); 
     } 
    } 
-1

Хитрость play with is BindingFlags.DeclaredOnly и IsSpecialName