184

Using dynamic pattern perhaps? You can call any method/property using the dynamic keyword, right? How to check whether the method exist before calling myDynamicObject.DoStuff(), for example?

Mikael Engver
  • 4,634
  • 4
  • 46
  • 53
Louis Rhys
  • 34,517
  • 56
  • 153
  • 221

5 Answers5

256

You could write something like that :

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

Edit : you can even do an extension method and use it like this

myObject.HasMethod("SomeMethod");
Fraser
  • 15,275
  • 8
  • 53
  • 104
Julien
  • 7,821
  • 3
  • 23
  • 16
  • GetType() will return the runtime type? (i.e. not object?) – Louis Rhys Feb 25 '11 at 07:01
  • 2
    yes, GetType() returns the running type whereas typeof() would return object. – Julien Feb 25 '11 at 07:03
  • 1
    According to the docs GetType() will return "The exact runtime type of the current instance". – tzup Feb 25 '11 at 07:03
  • Also, the extension method would need to be static. – Fraser Mar 15 '11 at 05:16
  • 10
    I prefer to write: objectToCheck.GetType().GetMethod(methodName) != null – efirat Sep 15 '12 at 09:18
  • Has explained in the comment after, you can use the new type dynamic : dynamic dynObj = myObject; dynObj.SomeMethod(); – Zitun Aug 29 '14 at 14:24
  • Extension methods don't work for `System.__COMObject`s for me; solution for me is to remove the `this` and use the method without the sugar. – bovender Jan 20 '17 at 05:21
  • I used this to make HasProperty() and HasEvent() methods. Will only find them if Public (and) has {get; set;}. Works well though... – rr789 Sep 04 '17 at 02:51
  • the type.GetMethod will throw an exception "ambiguous method" if there is overloads for this method in the targeted class! Beware. – Nicolas Belley Dec 11 '19 at 13:21
  • If you create an extension method on the object type it'll hang off every object that is in scope. That can get noisy. I needed this sort of thing in my test project so put it in a restrictive namespace to hide it from all but the one test class. – HarryTuttle Mar 10 '21 at 22:42
  • what about property? – AminFarajzadeh Feb 12 '22 at 10:02
104

via Reflection

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

Similar is for methods

Stecya
  • 22,896
  • 10
  • 72
  • 102
  • Nice. You could also do the GetMethod in a loop to get the appropriate defined property. – Jnr May 25 '17 at 12:13
  • Useful for looping through linked lists of UI controls and their Parents – Chicowitz Apr 19 '18 at 14:25
  • In `GetType()` there is method like `GetProperties()`. It is returning array of `PropertyInfo`. But how can I use `GetProperties()` method? – Yogesh Patel Mar 25 '19 at 04:56
54

It is an old question, but I just ran into it. Type.GetMethod(string name) will throw an AmbiguousMatchException if there is more than one method with that name, so we better handle that case

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
  • 10,638
  • 3
  • 36
  • 57
23

Wouldn't it be better to not use any dynamic types for this, and let your class implement an interface. Then, you can check at runtime wether an object implements that interface, and thus, has the expected method (or property).

public interface IMyInterface
{
   void Somemethod();
}


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

I think this is the only correct way.

The thing you're referring to is duck-typing, which is useful in scenarios where you already know that the object has the method, but the compiler cannot check for that. This is useful in COM interop scenarios for instance. (check this article)

If you want to combine duck-typing with reflection for instance, then I think you're missing the goal of duck-typing.

enjayem
  • 941
  • 8
  • 21
Frederik Gheysels
  • 56,135
  • 11
  • 101
  • 154
  • 2
    what if the object can be an object provided by the .NET framework, and I cannot declare it to implement anything? – Louis Rhys Feb 25 '11 at 09:39
  • What's the problem ? You can check whether the 'object' is such an object, provided by the .NET framework just in the same way – Frederik Gheysels Feb 25 '11 at 10:09
  • for example, you want to check whether there is an "Add" method in an object. ANd the object can be a List, or some other class that's not an IEnumerable – Louis Rhys Feb 25 '11 at 13:28
  • So, you have absolutely no idea which class you're using when using a .NET base class ? Can you show some real-life example code ? I think it smells. – Frederik Gheysels Feb 25 '11 at 13:31
  • 3
    Perhaps you should take a look at scripting an Adobe product with COM. The same function call can return entirely different COM objects, and by (Adobe's) design, their only common ancestor is object. Also: this is a commonplace pattern in pretty much any modern dynamic scripting language (Python, Javascript, VB script, PHP, Lua... I could go on and on). It's not a bug, it's a feature. – Tim Keating Dec 03 '11 at 14:36
  • 5
    It is a smell but it was created by microsoft. Look at WebControls such as Button, LinkButton, etc. They both implement OnClientClick property but, say, ListControl and Panel do not. OnClientClick is not defined in an interface so reflection is the only option. – HammerIp Oct 16 '12 at 12:41
  • Theatrically* this is the right way for high quality code *`...it would be easy to do if the test were hidden in a routine and hard to do if it were a complicated test hard-coded throughout the program. ` - Code Complete by Steve McConnell – user160357 Apr 01 '22 at 07:38
0

To avoid AmbiguousMatchException, I would rather say

objectToCheck.GetType().GetMethods().Count(m => m.Name == method) > 0
Alexander
  • 1,152
  • 1
  • 16
  • 18