Я делаю некоторый анализ типов во время выполнения с помощью Reflection. Если у меня есть экземпляр MethodInfo, как я могу выяснить, является ли это "реальным" методом или является методом getter/setter свойства? И если это свойство, как я могу найти его хостинг PropertyInfo?
Поиск хостинга PropertyInfo из MethodInfo для getter/setter
Ответ 1
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
Ну, метод геттера и сеттера - это "реальные" методы.
Отслеживание возврата к свойству - шаблон (return vs take 1 arg) поможет сузить его - но вам нужно будет вызвать GetGetMethod/GetSetMethod для каждого, чтобы найти свойство.
Вы можете , возможно, попробовать Name
(меньше get __/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();
}
}
Ответ 3
Посмотрите MethodBase.IsSpecialName
. Методы, которые не должны быть явно видны, например, аксессоры свойств, методы подписки на события и перегрузки операторов, используют этот флаг.
Насколько я знаю, нет способа найти PropertyInfo
без повторения через свойства и сравнения методов.
Ответ 4
Мне бы очень хотелось оставить это в качестве комментария, но я не могу, потому что мой представитель не достаточно высок: (
Theres ошибка в коде Marc Gravell: если его индексор возвращает null, даже если существует родительское свойство. Приятно иметь этот быстрый сбой, но я думаю, что мы можем сделать это только тогда, когда у него нет ни возвращаемого значения, ни параметра:
[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);
}
}
Ответ 5
Трюк для игры с BindingFlags.DeclaredOnly и IsSpecialName