Подтвердить что ты не робот

Поиск хостинга PropertyInfo из MethodInfo для getter/setter

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

4b9b3361

Ответ 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