Як використовувати Reflection для виклику перевантаженого методу в .NET


75

Чи є спосіб викликати перевантажений метод, використовуючи відображення в .NET (2.0). У мене є програма, яка динамічно створює екземпляри класів, похідних від загального базового класу. Для цілей сумісності цей базовий клас містить 2 однойменних методи, один із параметрами та один без. Мені потрібно викликати метод без параметрів за допомогою методу Invoke. Зараз я отримую лише помилку, яка повідомляє, що я намагаюся викликати неоднозначний метод.

Так, я міг просто передати об’єкт як екземпляр мого базового класу і викликати потрібний мені метод. В кінці кінців , що буде відбуватися, але прямо зараз, внутрішні ускладнення не дозволять.

Будь-яка допомога була б чудовою! Дякую.

Відповіді:


120

Ви повинні вказати, який метод ви хочете:

class SomeType 
{
    void Foo(int size, string bar) { }
    void Foo() { }
}

SomeType obj = new SomeType();
// call with int and string arguments
obj.GetType()
    .GetMethod("Foo", new Type[] { typeof(int), typeof(string) })
    .Invoke(obj, new object[] { 42, "Hello" });
// call without arguments
obj.GetType()
    .GetMethod("Foo", new Type[0])
    .Invoke(obj, new object[0]);

7
Ви також можете зробити Type.EmptyTypes
— yoel halb

2
need} після "typeof (int), typeof (string)" для компіляції :)
— Omid-RH

1
Що робити, якщо один із аргументів є загальним?
— Стівен Тернер

Коли у вас є екземпляр об’єкта, ви знаєте, з якими типами він був створений.
— Hallgrim

І якщо вам потрібно вказати параметр out, не базікайте з модифікаторами, це не працює (для мене). Вам потрібно передати об’єкт типу із властивістю IsByRef, встановленою в true. Однак IsByRef призначений лише для читання, вам потрібно використовувати метод MakeByRefType типу, щоб перетворити тип на екземпляр, який має цю властивість.
— Мартін Маат,

17

Так. Коли ви викликаєте метод, передайте параметри, які відповідають бажаному перевантаженню.

Наприклад:

Type tp = myInstance.GetType();

//call parameter-free overload
tp.InvokeMember( "methodName", BindingFlags.InvokeMethod, 
   Type.DefaultBinder, myInstance, new object[0] );

//call parameter-ed overload
tp.InvokeMember( "methodName", BindingFlags.InvokeMethod, 
   Type.DefaultBinder, myInstance, new { param1, param2 } );

Якщо ви робите це навпаки (тобто, знаходячи MemberInfo і викликаючи Invoke), будьте обережні, щоб отримати правильний - перевантаження без параметрів може бути першим знайденим.


Цікаво, що це не спрацювало. Я не передав жодних параметрів своєму безпараметричному методу, і все одно отримав неоднозначний виклик.
— Wes P

Як це працює з параметрами різних типів? Скажімо, у мене є дві перевантаження, коли одна бере рядок, а інша - int?
— smaclell

Не проблема - перевіряється основний тип параметрів.
— Кіт,

Слід бути обережним, коли у вас є типи, які неявно передаються один одному - тоді .Net вибирає методи екземпляра над успадкованими методами.
— Кіт,

Див. Це запитання для прикладу цього: stackoverflow.com/questions/154112
— Кіт,

5

Використовуйте перевантаження GetMethod, яке приймає System.Type [], і передайте порожній тип [];

typeof ( Class ).GetMethod ( "Method", new Type [ 0 ] { } ).Invoke ( instance, null );

3
Ви можете використовувати Type.EmptyTypes
— yoel halb
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.