2009-03-02 62 views
20

voglio creare un generico a cui posso passare una funzione come parametro, tuttavia questa funzione potrebbe includere parametri stesso modo ...Passare una funzione (con parametri) come parametro?

int foo = GetCachedValue("LastFoo", methodToGetFoo) 

Tale che:

protected int methodToGetFoo(DateTime today) 
{ return 2; // example only } 

Essenzialmente voglio avere un metodo che controllerà la cache per un valore, altrimenti genererà il valore basato sul metodo passato.

Pensieri?

+0

Non so come farlo, ma come nota, questa domanda non sembra avere nulla a che fare con i generici per quanto posso dire. – recursive

+0

In un certo senso, un po ', forse. Probabilmente "delegati" dovrebbero sostituire "generici". – mquander

+0

Siamo spiacenti, stavo creando un metodo generico per gestirlo, quindi ho assunto che fosse correlato. Ma il passaggio è veramente legato ai delegati, quindi aggiornerò. Grazie – klkitchens

risposta

37

Sembra che si desidera un Func<T>:

T GetCachedValue<T>(string key, Func<T> method) { 
    T value; 
    if(!cache.TryGetValue(key, out value)) { 
     value = method(); 
     cache[key] = value; 
    } 
    return value; 
} 

Il chiamante può quindi avvolgere questo in molti modi; per semplici funzioni:

int i = GetCachedValue("Foo", GetNextValue); 
... 
int GetNextValue() {...} 

o quando si tratta di argomenti, una chiusura:

var bar = ... 
int i = GetCachedValue("Foo",() => GetNextValue(bar)); 
+1

Grazie, ero molto vicino, ma non riuscivo a capire come ottenere i parms nel generico.L'ultima opzione, con la chiusura era la chiave! Funziona come un fascino. – klkitchens

+2

Davvero vecchio qui ma la parte di chiusura era proprio quello che stavo cercando –

4

è possibile creare il proprio delegato, ma in C# 3.0 si potrebbero trovare più conveniente utilizzare il built-in Func<T> delegato famiglia per risolvere questo problema. Esempio:

public int GetCachedValue(string p1, int p2, 
          Func<DateTime, int> getCachedValue) 
{ 
    // do some stuff in here 
    // you can call getCachedValue like any normal function from within here 
} 

Questo metodo avrà tre argomenti: una stringa, un int, e una funzione che prende un DateTime e restituisce un int. Ad esempio: esistono

int foo = GetCachedValue("blah", 5, methodToGetFoo); // using your method 
int bar = GetCachedValue("fuzz", 1, d => d.TotalDays); // using a lambda 

differente Func<T, U, V...> ecc tipi nel quadro per accogliere metodi con diverse quantità di argomenti.

3

crea un delegato per il metodo methodToGetFoo

public delegate object GenerateValue(params p); 
public event GenerateValue OnGenerateValue; 

Definire GetCachedValue di utilizzare il delegato

int GetCachedValue(string key, GenerateValue functionToCall); 

Poi, nella realizzazione di OnGenerateValue è possibile controllare i param di.

2

Here è qualcosa di semplice che ho iniziato che può essere portato un po 'oltre (come ho fatto per un progetto commerciale).

Nel mio caso questo è stato quello di memorizzare nella cache le chiamate di servizio web, ed è stato usato qualcosa come:

WebService ws = new WebService(); 
var result = ws.Call(x => x.Foo("bar", 1)); // x is the ws instance 
7

Utilizzando System.Action e di espressione lambda (metodo anonima). Per esempio

public void myMethod(int integer){ 

    //Do something 

} 

public void passFunction(System.Action methodWithParameters){ 

    //Invoke 
    methodWithParameters(); 

} 

//... 

//Pass anonimous method using lambda expression 
passFunction(() => myMethod(1234)); 
Problemi correlati