2010-08-18 19 views
7

Necesito un método que toma una Acción (o un Func), pero la Acción tiene un número mixto de parámetros. ¿Cuál es el modo más sencillo y compacto para implementar estas sobrecargas:C# Sobrecargas de parámetros Action y Func

public void Execute<T>(Action<T> action, T param) { 
    // TODO: Implement something like: 
    // Execute(action, param, null); 
} 

public void Execute<T1,T2>(Action<T1,T2> action, T1 param1, T2 param2) { 
    // TODO: Implement something like: 
    // Execute(action, param1, param2, null); 
} 

public void Execute<T1,T2,T3>(Action<T1,T2,T3> action, T1 param1, T2 param2, T3 param3) { 
    DoStuff(); 
    action(param1, param2, param3) 
    DoMoreStuff(); 
} 

// OR any other type of higher order function-solution 
public void Execute(Action action, params object[] parameters) { ... } // ??? 

El contenido de los métodos son exactamente los mismos, excepto para la ejecución de la acción y sus parámetros.

Si es posible, no use ninguna característica específica de C# 4.0 para solucionar esto.

Respuesta

8

El contenido de los métodos son exactamente el mismo, a excepción de la ejecución de la acción y sus parámetros.

que grita para el uso de un higher order function, pero puesto que ya parametrizar todos los bits que están cambiando (ejecución de la acción y sus parámetros) que está ya allí. Lo sentimos, parece que tendrás que implementar estas sobrecargas manualmente.

Simplemente encadenar mediante el uso de valores nulos no funcionará ya que los delegados aprobados no coinciden. Lo que podría hacer es envuelven la acción/func pasado dentro de un lambda de pelar argumentos adicionales:

public void Execute(Action<T> action, T param) { 
    Execute((a, _) => action(a) , param, null); 
} 

public void Execute(Action<T1, T2> action, T1 param1, T2 param2) { 
    Execute((a, b, _) => action(a, b) , param1, param2, null); 
} 

public void Execute(Action<T1, T2, T3> action, T1 param1, T2 param2, T3 param3) { 
    DoStuff(); 
    action(param1, param2, param3) 
    DoMoreStuff(); 
} 
+0

No dude en proporcionar una solución de función de orden superior. –

+0

@Seb: En cuanto a la función de orden superior: Ya estás allí al haber parametrizado tu acción. –

5

Esto es en realidad el mejor enfoque (teniendo en punto de la mente de Johannes que podría haber también utilizaron un mayor función de orden), ya que es la más amigable (los delegados se asociarán automáticamente con el número correcto y los tipos de argumentos) y no requiere ninguna llamada molesta DynamicInvoke.

Sin embargo, su última definición de método es problemática. Un Action por su propia naturaleza no acepta ningún parámetro, por lo que no va a jugar bien con un argumento params object[]. Si quieres una sobrecarga final que acepta un número variable de argumentos, me gustaría ir con DynamicInvoke después de todo, sólo para esta llamada de método:

public void Execute(Delegate action, params object[] parameters) 
{ 
    DoStuff(); 
    action.DynamicInvoke(parameters); 
    DoMoreStuff(); 
} 

Sin embargo, para ampliar lo Johannes estaba diciendo, creo que era básicamente que apunta a algo como esto:

public Action<T1, T2, T3> CreateAction<T1, T2, T3>(Action action) 
{ 
    return (T1 x, T2 y, T3 z) => action(); 
} 

public Action<T1, T2, T3> CreateAction<T1, T2, T3>(Action<T1> action, T1 arg) 
{ 
    return (T1 x, T2 y, T3 z) => action(arg); 
} 

Y así sucesivamente - en otras palabras, lo que has hecho ya, pero en un contexto general, de manera que el código es reutilizable en otros lugares.

Cuestiones relacionadas