¿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?


¿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");

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


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;
    }
} 

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.


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.