.net - Encontrar el alojamiento PropertyInfo del MethodInfo de getter/setter
reflection (5)
Hago algunos análisis de tipo en tiempo de ejecución usando Reflection. Si tengo una instancia de MethodInfo, ¿cómo puedo averiguar si este es un método "real" o es un método getter / setter de una propiedad? Y si es una propiedad, ¿cómo puedo encontrar de nuevo el hosting PropertyInfo?
Bueno, el método detrás de un getter y setter son métodos "reales".
Volver a rastrear a una propiedad: el patrón (return vs take 1 arg) lo ayudará a reducirlo, pero tendrá que llamar a GetGetMethod / GetSetMethod en cada uno para encontrar la propiedad.
Probablemente puedas probar el Name
(menos obtener __ / set__), pero eso se siente frágil. Aquí está la versión más larga (sin uso de 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();
}
}
Ecma 335 especifica (pero no exige) que los compiladores usen los prefijos get_ / set_ (capítulo 22.28). No conozco ningún idioma que rompa esa recomendación. Haciéndolo fácil:
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);
}
El truco para jugar es BindingFlags.DeclaredOnly e IsSpecialName
Mire en MethodBase.IsSpecialName
. Los métodos que no deben ser claramente visibles, como los descriptores de acceso a propiedades, los métodos de suscripción a eventos y las sobrecargas del operador, utilizan este indicador.
Que yo sepa, no hay una manera de encontrar el PropertyInfo
sin iterar a través de las propiedades y comparar los métodos.
Realmente me gustaría dejar esto como un comentario, pero no puedo porque mi representante no es lo suficientemente alto :(
Hay un error en el código de Marc Gravell: si es un indexador devolverá nulo, incluso cuando exista una propiedad principal. Es bueno tener esa falla rápida, pero creo que solo podemos hacerlo cuando no tiene un valor de retorno o un parámetro:
[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);
}
}