¿Cómo verificar si un objeto tiene cierto método / propiedad?

155

¿Usando un patrón dinámico quizás? Puede llamar a cualquier método / propiedad utilizando la palabra clave dinámica, ¿verdad? ¿Cómo verificar si el método existe antes de llamar a myDynamicObject.DoStuff (), por ejemplo?

Louis Rhys
fuente
¿Cuál es el tipo de myDynamicObject ? ¿Es una clase derivada de DynamicObject?
Cheng Chen
algo declarado con la palabra clave dinámica
Louis Rhys

Respuestas:

224

Podrías escribir algo así:

public static bool HasMethod(this object objectToCheck, string methodName)
{
    var type = objectToCheck.GetType();
    return type.GetMethod(methodName) != null;
} 

Editar: incluso puedes hacer un método de extensión y usarlo así

myObject.HasMethod("SomeMethod");
Julien
fuente
GetType () devolverá el tipo de tiempo de ejecución? (es decir, no objeto?)
Louis Rhys
2
Sí, GetType () devuelve el tipo de ejecución, mientras que typeof () devolvería el objeto.
Julien
1
Según los documentos, GetType () devolverá "El tipo de tiempo de ejecución exacto de la instancia actual".
tzup
Además, el método de extensión debería ser estático.
Fraser
9
Prefiero escribir: objectToCheck.GetType (). GetMethod (methodName)! =
Null
85

a través de la reflexión

 var property = object.GetType().GetProperty("YourProperty")
 property.SetValue(object,some_value,null);

Similar es para métodos

Stecya
fuente
Agradable. También puede hacer GetMethod en un bucle para obtener la propiedad definida adecuada.
Jnr
Útil para recorrer listas enlazadas de controles de UI y sus padres
Chicowitz
En GetType()hay un método como GetProperties(). Está devolviendo la matriz de PropertyInfo. Pero, ¿cómo puedo usar el GetProperties()método?
Yogesh Patel
43

Es una vieja pregunta, pero me la encontré. Type.GetMethod(string name)lanzará una AmbiguousMatchException si hay más de un método con ese nombre, por lo que es mejor que manejemos ese caso

public static bool HasMethod(this object objectToCheck, string methodName)
{
    try
    {
        var type = objectToCheck.GetType();
        return type.GetMethod(methodName) != null;
    }
    catch(AmbiguousMatchException)
    {
        // ambiguous means there is more than one result,
        // which means: a method with that name does exist
        return true;
    }
} 
esskar
fuente
18

¿No sería mejor no usar ningún tipo dinámico para esto y dejar que su clase implemente una interfaz? Luego, puede verificar en tiempo de ejecución si un objeto implementa esa interfaz y, por lo tanto, tiene el método (o propiedad) esperado.

public interface IMyInterface
{
   void Somemethod();
}


IMyInterface x = anyObject as IMyInterface;
if( x != null )
{
   x.Somemethod();
}

Creo que esta es la única forma correcta.

A lo que te refieres es a escribir pato, lo cual es útil en escenarios en los que ya sabes que el objeto tiene el método, pero el compilador no puede verificarlo. Esto es útil en escenarios de interoperabilidad COM, por ejemplo. (mira este artículo)

Si desea combinar la escritura de pato con la reflexión, por ejemplo, creo que se está perdiendo el objetivo de la escritura de pato.

Frederik Gheysels
fuente
2
¿Qué pasa si el objeto puede ser un objeto proporcionado por .NET Framework y no puedo declarar que implemente nada?
Louis Rhys
Cuál es el problema ? Puede verificar si el 'objeto' es un objeto de este tipo, proporcionado por .NET Framework de la misma manera
Frederik Gheysels,
por ejemplo, desea verificar si hay un método "Agregar" en un objeto. Y el objeto puede ser una Lista <int>, o alguna otra clase que no sea un IEnumerable
Louis Rhys
3
Quizás debería echarle un vistazo a la creación de scripts de un producto de Adobe con COM. La misma llamada de función puede devolver objetos COM completamente diferentes y, por diseño (de Adobe), su único antecesor común es el objeto. Además: este es un patrón común en casi cualquier lenguaje de script dinámico moderno (Python, Javascript, script VB, PHP, Lua ... podría seguir y seguir). No es un error, es una característica.
Tim Keating
55
Es un olor pero fue creado por microsoft. Mire los controles web como Button, LinkButton, etc. Ambos implementan la propiedad OnClientClick pero, digamos, ListControl y Panel no. OnClientClick no está definido en una interfaz, por lo que la reflexión es la única opción.
HammerIp