Как я могу программно сделать разрешение перегрузки метода в C#?
Когда компилятор C# интерпретирует вызов метода, он должен использовать (статические) типы аргументов, чтобы определить, какая перегрузка действительно вызывается. Я хочу быть в состоянии сделать это программно.
Если у меня есть название метода (string
), тип, который объявляет это (экземпляр System.Type
), и список типов аргументов, которые я хочу иметь возможность вызывать стандартную библиотечную функцию и получить обратно MethodInfo
объект, представляющий метод, который компилятор C# выберет для вызова.
Например, если у меня есть
class MyClass {
public void myFunc(BaseClass bc) {};
public void myFunc(DerivedClass dc) {};
}
Тогда я хочу что-то вроде этой вымышленной функции GetOverloadedMethod
на System.Type
MethodInfo methodToInvoke
= typeof(MyClass).GetOverloadedMethod("myFunc", new System.Type[] {typeof(BaseClass)});
В этом случае methodToInvoke
должно быть public void myFunc(BaseClass bc)
,
ПРИМЕЧАНИЕ: ни один из методов GetMethod
а также GetMethods
будет служить моей цели. Ни один из них не имеет никакого разрешения перегрузки. В случае GetMethod
он возвращает только точные совпадения. Если вы дадите ему более производные аргументы, он просто ничего не вернет. Или вам может посчастливиться получить исключение двусмысленности, которое не дает никакой полезной информации.
1 ответ
Ответ
использование Type.GetMethod(String name, Type[] types)
сделать программное разрешение перегрузки. Вот пример:
MethodInfo methodToInvoke = typeof(MyClass)
.GetMethod("myFunc", new System.Type[] { typeof(BaseClass) });
объяснение
В примере methodToInvoke
будет myFunc(BaseClass bc)
не myFunc(DerivedClass dc)
, поскольку types
массив определяет список параметров метода, чтобы получить.
Из документации MSDN, Type.GetMethod(String name, Type[] types)
имеет два параметра:
name
это имя метода, чтобы получить, иtypes
предоставляет порядок, количество и типы параметров метода.
Запуск кода
Вот бегущая скрипка, которая демонстрирует программное разрешение перегрузки.
using System;
using System.Reflection;
public static class Program
{
public static void Main()
{
MethodInfo methodToInvoke = typeof(MyClass)
.GetMethod("myFunc", new System.Type[] { typeof(BaseClass) });
var result = methodToInvoke
.Invoke(new MyClass(), new object[] { new BaseClass() });
Console.WriteLine(result);
}
public class MyClass
{
public static string myFunc(BaseClass bc) {
return "BaseClass";
}
public static string myFunc(DerivedClass dc) {
return "DerivedClass";
}
}
public class BaseClass { }
public class DerivedClass : BaseClass { }
}
Выход BaseClass
,
Изменить: это надежный.
GetMethod
решенные методы, которые принимают params
более производные классы, делегаты и реализации интерфейса. Эта скрипка демонстрирует все эти случаи. Вот звонки и что они получают.
Работает с params
MethodInfo methodToInvoke2 = typeof(MyClass).GetMethod(
"myFunc",
new System.Type[] { typeof(Int32[]) });
разрешит этот метод
public static string myFunc(params int[] i)
{
return "params";
}
Работает с более производными классами
MethodInfo methodToInvoke3 = typeof(MyClass).GetMethod(
"myFunc",
new System.Type[] { typeof(MoreDerivedClass) });
разрешает метод, который принимает MoreDerivedClass
public class BaseClass { }
public class DerivedClass : BaseClass { }
public class MoreDerivedClass : DerivedClass {}
Работает с делегатами
MethodInfo methodToInvoke4 = typeof(MyClass).GetMethod(
"myFunc",
new System.Type[] { typeof(MyDelegate) });
... получит метод, который принимает этот делегат:
public delegate void MyDelegate(string x);
Работает с реализациями интерфейса
MethodInfo methodToInvoke5 = typeof(MyClass).GetMethod(
"myFunc",
new System.Type[] { typeof(MyImplementation) });
... успешно получает метод, который принимает MyImplementation
public interface IMyInterface {}
public class MyImplementation : IMyInterface {}
Таким образом, это надежно, и мы можем использовать GetMethod
делать разрешение перегрузки в тех случаях, когда мы не ожидаем, что сработает.