Я делаю некоторый анализ типа во время выполнения с использованием Reflection. Если у меня есть экземпляр MethodInfo, , как я могу выяснить, является ли это «реальным» методом или является методом getter/setter свойства? И если это свойство, как я могу найти его хостинг PropertyInfo обратно?Поиск хостинга PropertyInfo из MethodInfo из getter/setter
ответ
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);
}
Ну, метод за геттером и сеттером : «реальные» методы.
Отслеживание возврата к свойству - шаблон (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();
}
}
+1 для обходного пути, по-прежнему предпочитают имя .StartsWith ("get_"/"set_") '. – arul
hmm ... возможно, для кода C#, по крайней мере ... они упомянуты в 17.2.7.1 ECMA 335 - но применимо ли это к другим языкам? Я проверю ECMA 334 ... –
Уверен, что это, проверьте раздел 17.2.7.1. Для свойства P типа T зарезервированы следующие подписи: T get_P(); void set_P (значение T); Обе подписи зарезервированы, даже если свойство доступно только для чтения или только для записи. – arul
Посмотрите на MethodBase.IsSpecialName
. Эти флаги используют методы, которые не должны быть явно видимыми, например, аксессоры свойств, методы подписки на события и перегрузки операторов.
Насколько я знаю, нет способа найти PropertyInfo
без повторного использования свойств и сравнения методов.
Согласно MS, вы не можете гарантировать, что будет установлен флаг IsSpecialName: http://connect.microsoft.com/VisualStudio/feedback/details/108302/for-property-accessors-get-set-isspecialname-false –
IsSpecialName действительно работает. Я надеюсь, что это нечто изменило MS, потому что лучше иметь возможность проверять флаг, а не объяснять, какие языковые функции реализованы как (возможно, немаркированные) специальные методы. –
Я бы очень хотел, чтобы оставить это в качестве комментария, но я не могу, так как мое повторение не достаточно высокого :(
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);
}
}
Хитрость play with is BindingFlags.DeclaredOnly и IsSpecialName
Из информационного текста требуется, чтобы он соответствовал требованиям CLS, но не требовался, чтобы быть действительным IL. –
Я бы не рекомендовал идти этим путем. Я рекомендую проверить все свойства. Контур шаблона строк - не устойчивый. –
Хотелось бы увидеть встречный пример. –