referencia - pasar objetos como parametros en c#
¿Cómo pasar una función como parámetro en C#? (8)
Algo como esto debería funcionar para usted:
delegate int MyDelegate(int a, int b);
public int Add(int a, int b) {
return a + b;
}
public void InvokeMethod(Delegate method, object[] param) {
Console.WriteLine(method.DynamicInvoke(param));
}
public Form1() {
InitializeComponent();
InvokeMethod(new MyDelegate(Add), new object[] { 1, 2 });
}
¡Buena suerte!
¿Es posible pasar una función como parámetro en C #? Puedo hacerlo utilizando las clases Func o Action, pero esto me obliga a declarar toda la firma de la función a la vez. Cuando trato de usar Delegate, aparece un error de compilación que dice que no puede convertir un grupo de métodos en Delegado.
Estoy trabajando en Axial e intento permitir que los usuarios llamen a servicios web. Lo que estoy buscando es la capacidad de crear la clase proxy de Visual Studio y luego pasar la función generada. La firma de la función no importa porque el código generado solo usa el nombre de la función. Sin embargo, me gustaría pasar la función en lugar del nombre por dos razones: la capacidad de usar la propiedad Url del proxy y un error de compilación si el servicio web no existe o está actualizado en Visual Studio.
public void AlertIt(object o) {
Axial.DOM.Window.Alert(o.ToString());
}
public void CallAddService() {
object[] param = new object[] { int.Parse(txtA.Text), int.Parse(txtB.Text) };
Axial.ServerScript.CallWebService(new WSProxy.WS().Add, param, AlertIt, AlertIt);
}
class Axial.ServerScript {
public void CallWebService(Delegate method, object[] param, Action<object> successCallback, Action<object> failureCallback) {
// translate to javascript (already working)
}
}
Creo que lo que quieres es:
static object InvokeMethod(Delegate method, params object[] args){
return method.DynamicInvoke(args);
}
static int Add(int a, int b){
return a + b;
}
static void Test(){
Console.WriteLine(InvokeMethod(new Func<int, int, int>(Add), 5, 4));
}
Imprime "9".
Deberías tener un delegado primero
delegate int Operation(int a, int b)
entonces se convierte en:
public void InvokeMethod(Operation method, object target, object param)
{
method((int) target, (int) param);
}
No hay necesidad de llamar a Invoke.
Al igual que con dbone, no estoy seguro de por qué necesitarías una matriz params []. ¿Podría aclarar el uso ampliado de los params?
Además, tendré que corregir algo en tu pregunta, porque provocará un error de compilación: p
Di si necesitas pasar el método como parámetro y también necesitas capturar el valor de retorno para un procesamiento posterior. Entonces los ejemplos anteriores funcionarán bien. Pero supongamos que si necesita pasar un método con un tipo de retorno nulo, entonces necesita crear una versión más de la función InvokeMethod. Verifica el ejemplo a continuación.
private static T retry<T>(Delegate method, params object[] args)
{
for (int i = 0; i <= 3; i++)
{
try
{
return (T)method.DynamicInvoke(args);
}
catch (Exception ex)
{
if (i == 3)
{
logMessage(ex.Message);
}
Console.WriteLine("Retry count " + i);
Thread.Sleep(10);
}
}
return default(T);
}
private static void retry2(Delegate method, params object[] args)
{
for (int i = 0; i <= 3; i++)
{
try
{
method.DynamicInvoke(args);
break;
}
catch (Exception ex)
{
if (i == 3)
{
logMessage(ex.Message);
//return default(T);
}
Console.WriteLine("Retry count " + i);
Thread.Sleep(10);
}
}
}
static bool isSuccess = true;
static void logMessage(string msg)
{
isSuccess = false;
Console.WriteLine(msg);
}
static int Add(int a, int b)
{
return a + b;
}
static void Add2(int a, int b)
{
int c = a + b;
Console.WriteLine(c);
}
static void Main(string[] args)
{
int d = retry<int>(new Func<int, int, int>(Add), 6, 7.7);
Console.Write(" " + d + "/n"+isSuccess);
retry2(new Action<int, int>(Add2), 45, 60);
Console.ReadKey();
}
Este es un ejemplo muy simple para el programador que ya está familiarizado con la función de pase de estilo ( C / C ++ / VB.NET/Python ) por puntero / ref (con delegado C # ):
delegate void CALLBACK(String s);
static void Main(string[] args)
{
Get("some string", testfunc);
Util.pause();
}
static void Get(String s, CALLBACK x)
{
x(s);
}
static void testfunc(String s)
{
Console.WriteLine(s);
}
La conversión de un grupo de métodos, método anónimo o expresión lambda a un delegado requiere que el compilador sepa el tipo exacto de delegado. Sin embargo, podría utilizar expresiones lambda y variables capturadas para simplificar esto:
public void InvokeMethod(Action action)
{
action();
}
public int Add(int a, int b)
{
return a + b;
}
public void Test()
{
InvokeMethod(() => Add(2, 3));
}
Eso básicamente retrasa la invocación de la manera normal, pero ajustando la llamada real a Add
en un delegado de Action
simple.
Si eso no cumple con sus requisitos, quizás pueda decirnos un poco más sobre lo que realmente está tratando de lograr.
EDITAR: si se trata de un código generado, puede convertirlo a un Func<...>
con los argumentos de tipo correctos, suponiendo que no haya demasiados. Aparte de eso, no hay una forma real de pasar a un grupo de métodos. Ha habido llamadas ocasionales para un operador de "infoof (...)" (como typeof pero para miembros) que le daría un MemberInfo, pero eso realmente no existe.
Vea la serie de programación funcional de Justin Etheredge. Debería encontrar una solución a su problema allí.
echa un vistazo al uso de delegados aquí es un gran ejemplo
¿Por qué estás usando la reflexión? ¿habrá alguna vez un número diferente de params? o ¿sabe usted que el método signture se mantendrá constante (también recuerde que C # admite la palabra clave params [])
HTH
Huesos