Як використовувати 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.