Como verificar se um objeto tem determinado método / propriedade?

155

Usando padrão dinâmico, talvez? Você pode chamar qualquer método / propriedade usando a palavra-chave dinâmica, certo? Como verificar se o método existe antes de chamar myDynamicObject.DoStuff (), por exemplo?

Louis Rhys
fonte
Qual é o tipo de myDynamicObject ? É uma classe derivada DynamicObject?
Cheng Chen
algo declarado com a palavra
Louis Rhys

Respostas:

224

Você poderia escrever algo assim:

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

Editar: você pode até fazer um método de extensão e usá-lo assim

myObject.HasMethod("SomeMethod");
Julien
fonte
GetType () retornará o tipo de tempo de execução? (ou seja, não se opõe?)
Louis Rhys
2
Sim, GetType () retorna o tipo em execução, enquanto typeof () retornaria objeto.
Julien
1
De acordo com os documentos, GetType () retornará "O tipo de tempo de execução exato da instância atual".
tzup 25/02
Além disso, o método de extensão precisaria ser estático.
Fraser
9
Eu prefiro escrever: objectToCheck.GetType (). GetMethod (methodName)! =
Null
85

via Reflexão

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

Semelhante é para métodos

Stecya
fonte
Agradável. Você também pode executar o GetMethod em um loop para obter a propriedade definida apropriada.
quer
Útil para loop através listas ligadas de controles de interface do usuário e seus pais
Chicowitz
Em GetType()existe um método como GetProperties(). Está retornando matriz de PropertyInfo. Mas como posso usar o GetProperties()método?
usar o seguinte
43

É uma pergunta antiga, mas acabei de encontrar. Type.GetMethod(string name)lançará uma AmbiguousMatchException se houver mais de um método com esse nome, então é melhor lidarmos com esse 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
fonte
18

Não seria melhor não usar nenhum tipo dinâmico para isso e deixar sua classe implementar uma interface. Em seguida, você pode verificar em tempo de execução se um objeto implementa essa interface e, portanto, possui o método (ou propriedade) esperado.

public interface IMyInterface
{
   void Somemethod();
}


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

Eu acho que essa é a única maneira correta.

Você está se referindo à digitação de pato, o que é útil em cenários em que você já sabe que o objeto tem o método, mas o compilador não pode verificar isso. Isso é útil em cenários de interoperabilidade COM, por exemplo. (consulte este artigo)

Se você deseja combinar digitação de patos com reflexão, por exemplo, acho que está perdendo o objetivo de digitar patos.

Frederik Gheysels
fonte
2
e se o objeto puder ser um objeto fornecido pela estrutura .NET e não posso declarar que implementa alguma coisa?
Louis Rhys
Qual é o problema ? Você pode verificar se o 'objeto' é um objeto desse tipo, fornecido pela estrutura .NET da mesma maneira #
Frederik Gheysels
por exemplo, você deseja verificar se existe um método "Adicionar" em um objeto. Eo objeto pode ser um List <int>, ou alguma outra classe que não é um IEnumerable
Louis Rhys
3
Talvez você deva dar uma olhada no script de um produto Adobe com COM. A mesma chamada de função pode retornar objetos COM totalmente diferentes e, pelo design (da Adobe), seu único ancestral comum é o objeto. Além disso: esse é um padrão comum em praticamente qualquer linguagem de script dinâmica moderna (Python, Javascript, script VB, PHP, Lua ... eu poderia continuar). Isto não é um erro, é um recurso.
Tim Keating
5
É um cheiro, mas foi criado pela microsoft. Veja WebControls como Button, LinkButton, etc. Ambos implementam a propriedade OnClientClick, mas, digamos, ListControl e Panel não. OnClientClick não está definido em uma interface, portanto a reflexão é a única opção.
HammerIp