sobreescritura - ¿Cómo puedo programar la resolución de sobrecarga de métodos en C#?
sobrecarga y escritura c# (1)
Cuando el compilador de C # interpreta una invocación de método, debe usar tipos de argumentos (estáticos) para determinar qué sobrecarga realmente se está invocando. Quiero poder hacer esto programáticamente.
Si tengo el nombre de un método (una string
), el tipo que lo declara (una instancia de System.Type
), y una lista de tipos de argumentos, quiero poder llamar a una función de biblioteca estándar y recuperar un objeto MethodInfo
representando el método que el compilador de C # elegiría invocar.
Por ejemplo si tengo
class MyClass {
public void myFunc(BaseClass bc) {};
public void myFunc(DerivedClass dc) {};
}
Entonces quiero algo como esta función ficticia GetOverloadedMethod
en System.Type
MethodInfo methodToInvoke
= typeof(MyClass).GetOverloadedMethod("myFunc", new System.Type[] {typeof(BaseClass)});
En este caso, methodToInvoke
debe ser public void myFunc(BaseClass bc)
.
NOTA : ninguno de los métodos GetMethod
y GetMethods
servirá para mi propósito. Ninguno de ellos hace ninguna resolución de sobrecarga. En el caso de GetMethod
solo devuelve coincidencias exactas. Si le das más argumentos derivados, simplemente no devolverá nada. O puede que tenga la suerte de obtener una excepción de ambigüedad que no proporciona información útil.
Responder
Use Type.GetMethod(String name, Type[] types)
para hacer la resolución de sobrecarga programática. Aquí hay un ejemplo:
MethodInfo methodToInvoke = typeof(MyClass)
.GetMethod("myFunc", new System.Type[] { typeof(BaseClass) });
Explicación
En el ejemplo, methodToInvoke
será myFunc(BaseClass bc)
no myFunc(DerivedClass dc)
, porque la matriz de types
especifica la lista de parámetros del método a obtener.
De la documentación de MSDN , Type.GetMethod(String name, Type[] types)
tiene dos parámetros:
-
name
es el nombre del método a obtener, y -
types
proporciona el orden, número y tipos de parámetros del método.
Código de funcionamiento
Aquí hay un violín en ejecución que demuestra la resolución de sobrecarga programática.
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 { }
}
La salida es BaseClass
.
Edición: Esto es robusto.
GetMethod
resolvió métodos que toman params
, más clases derivadas, delegados e implementaciones de interfaz. Este violín demuestra todos esos casos . Aquí están las llamadas y lo que recuperan.
Trabaja con params
MethodInfo methodToInvoke2 = typeof(MyClass).GetMethod(
"myFunc",
new System.Type[] { typeof(Int32[]) });
resolverá este método
public static string myFunc(params int[] i)
{
return "params";
}
Trabaja con más clases derivadas.
MethodInfo methodToInvoke3 = typeof(MyClass).GetMethod(
"myFunc",
new System.Type[] { typeof(MoreDerivedClass) });
resuelve un método que toma el MoreDerivedClass
public class BaseClass { }
public class DerivedClass : BaseClass { }
public class MoreDerivedClass : DerivedClass {}
Trabaja con delegados
MethodInfo methodToInvoke4 = typeof(MyClass).GetMethod(
"myFunc",
new System.Type[] { typeof(MyDelegate) });
... recuperará un método que toma este delegado:
public delegate void MyDelegate(string x);
Funciona con implementaciones de interfaz.
MethodInfo methodToInvoke5 = typeof(MyClass).GetMethod(
"myFunc",
new System.Type[] { typeof(MyImplementation) });
... recupera con éxito un método que toma MyImplementation
public interface IMyInterface {}
public class MyImplementation : IMyInterface {}
Por lo tanto, es robusto y podemos usar GetMethod
para realizar la resolución de sobrecargas en los casos en los que no esperemos que funcionen.