2010-08-18 43 views
7

Ich brauche eine Methode, die eine Aktion (oder eine Func), aber die Aktion hat eine gemischte Anzahl von Parametern. Was ist die direkteste und kompakte Art und Weise dieser Überlastungen zu implementieren:C# Aktion und Func Parameter Überladungen

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) { ... } // ??? 

Der Inhalt der Methoden sind genau die gleiche, mit Ausnahme der Ausführung der Aktion und deren Parameter.

Verwenden Sie nach Möglichkeit keine C# 4.0-spezifischen Funktionen, um dies zu beheben.

Antwort

8

Der Inhalt der Verfahren sind genau die gleichen, außer für die Ausführung der die Aktion und ihre Parameter.

dass ein higher order function für die Verwendung schreit, aber da Sie bereits parametriert alle Bits, die (Ausführung der Aktion und deren Parameter) Sie sind schon da ändern sich. Entschuldigung, es sieht so aus, als müssten Sie diese Überladungen manuell implementieren.

Die Verkettung mit Nullen funktioniert nicht, da die übergebenen Delegierten nicht übereinstimmen. Was könnten Sie tun, ist die übergebene Aktion/func in einem Lambda-wickeln zusätzliche Argumente abzuschälen:

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

Bitte zögern Sie nicht, auch eine Funktion-Lösung höherer Ordnung zu bieten. –

+0

@Seb: Bezüglich der Funktion höherer Ordnung: Sie sind bereits da, indem Sie Ihre Aktion parametrisiert haben. –

5

Dies ist eigentlich der beste Ansatz (unter Berücksichtigung der Tatsache Johannes der Punkt, dass Sie könnte habe auch eine höhere Ordnungsfunktion), da es am typsichersten ist (Delegaten werden automatisch mit der richtigen Anzahl und den richtigen Argumenten abgeglichen) und erfordert keine störenden DynamicInvoke Aufrufe.

Ihre letzte Methodendefinition ist jedoch problematisch. Eine Action akzeptiert von Natur aus keine Parameter, so dass es mit einem params object[] Argument nicht schön spielen wird. Wenn Sie eine endgültige Überlastung mögen, die eine variable Anzahl von Argumenten akzeptiert, ich mit DynamicInvoke schließlich gehen würde, nur für diesen Methodenaufruf:

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

Aber zu erweitern, was Johannes sagen war, ich glaube, er war im Grunde genommen bei so etwas wie diese bekommen:

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); 
} 

Und so weiter - in anderen Worten, was haben Sie bereits getan, aber in einem allgemeinen Kontext, so dass der Code in anderen Orten wiederverwendbar.