Как проверить, есть ли у объекта определенный метод / свойство?

156

Использование динамического шаблона возможно? Вы можете вызвать любой метод / свойство, используя ключевое слово dynamic, верно? Как проверить, существует ли метод, например, перед вызовом myDynamicObject.DoStuff ()?

Луис Рис
источник
Какой тип myDynamicObject ? Это класс, полученный из DynamicObject?
Ченг Чен
что-то объявлено с динамическим ключевым словом
Луи Рис

Ответы:

225

Вы могли бы написать что-то вроде этого:

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

Изменить: вы даже можете сделать метод расширения и использовать его следующим образом

myObject.HasMethod("SomeMethod");
Julien
источник
GetType () вернет тип времени выполнения? (то есть не объект?)
Луи Рис
2
да, GetType () возвращает тип выполнения, тогда как typeof () возвращает объект.
Жюльен
1
Согласно документации, GetType () вернет «Точный тип времени выполнения текущего экземпляра».
tzup
Кроме того, метод расширения должен быть статическим.
Фрейзер
9
Я предпочитаю писать: objectToCheck.GetType (). GetMethod (methodName)! =
Null
85

через отражение

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

Похоже на методы

Stecya
источник
Ницца. Вы также можете сделать GetMethod в цикле, чтобы получить соответствующее определенное свойство.
Jnr
Полезно для циклического просмотра связанных списков элементов управления пользовательского интерфейса и их родителей
Chicowitz,
В GetType()есть метод вроде GetProperties(). Возвращается массив PropertyInfo. Но как я могу использовать GetProperties()метод?
Йогеш Патель
43

Это старый вопрос, но я просто столкнулся с ним. Type.GetMethod(string name)вызовет AmbiguousMatchException, если существует более одного метода с таким именем, поэтому мы лучше обработаем этот случай

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
источник
18

Не лучше ли для этого не использовать динамические типы и позволить вашему классу реализовать интерфейс. Затем вы можете проверить во время выполнения, реализует ли объект этот интерфейс, и, таким образом, имеет ожидаемый метод (или свойство).

public interface IMyInterface
{
   void Somemethod();
}


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

Я думаю, что это единственный правильный путь.

То, к чему вы обращаетесь, это типизирование утки, что полезно в сценариях, когда вы уже знаете, что у объекта есть метод, но компилятор не может проверить это. Это полезно, например, в сценариях взаимодействия COM. (проверьте это статью)

Если вы хотите сочетать, например, типизацию утки с отражением, то я думаю, что вам не хватает цели типизации утки.

Фредерик Гейсель
источник
2
Что делать, если объект может быть объектом, предоставленным .NET Framework, и я не могу объявить его для реализации чего-либо?
Луи Рис
В чем проблема ? Вы можете проверить, является ли «объект» таким объектом, предоставленным платформой .NET точно таким же образом
Фредерик Гейселс,
например, вы хотите проверить, есть ли в объекте метод «Добавить». И объект может быть List <int> или другим классом, который не является IEnumerable
Louis Rhys
3
Возможно, вам стоит взглянуть на сценарии продукта Adobe с COM. Один и тот же вызов функции может возвращать совершенно разные COM-объекты, и по замыслу (Adobe) их единственным общим предком является объект. Кроме того: это обычная модель практически во всех современных динамических скриптовых языках (Python, Javascript, VB script, PHP, Lua ... Я мог бы продолжать и продолжать). Это не ошибка, это особенность.
Тим Китинг
5
Это запах, но он был создан Microsoft. Посмотрите на WebControls, такие как Button, LinkButton и т. Д. Они оба реализуют свойство OnClientClick, но, скажем, ListControl и Panel этого не делают. OnClientClick не определен в интерфейсе, поэтому отражение является единственным вариантом.
HammerIp