toma sobreescritura sobrecarga programacion polimorfismo para orientada objetos ninguna metodos metodo escritura ejemplos ejemplo argumentos c# reflection system.reflection overload-resolution system-codedom-compiler

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.