Domanda

Voglio creare un generico a cui posso passare una funzione come parametro, tuttavia questa funzione può includere i parametri stessi quindi ...

int foo = GetCachedValue("LastFoo", methodToGetFoo)

Tale che:

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

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

Pensieri?

È stato utile?

Soluzione

Sembra che tu voglia 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 avvolgerlo in molti modi; per funzioni semplici:

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

o dove sono coinvolti argomenti, una chiusura:

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

Altri suggerimenti

Uso di System.Action ed espressione lambda (metodo anonimo). Ad 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));

Puoi creare il tuo delegato, ma in C # 3.0 potresti trovare più comodo usare la famiglia di delegati Func<T> integrata 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 prenderà tre argomenti: una stringa, un int e una funzione che accetta un DateTime e restituisce un int. Ad esempio:

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

Esistono diversi tipi di Func<T, U, V...> ecc. nel framework per adattarsi a metodi con diverse quantità di argomenti.

Crea un delegato per il metodo methodToGetFoo

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

Definisci GetCachedValue per usare il delegato

int GetCachedValue(string key, GenerateValue functionToCall);

Quindi nell'implementazione di OnGenerateValue puoi controllare i parametri.

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

Nel mio caso si trattava di memorizzare nella cache le chiamate ai servizi Web e veniva usato in qualcosa del tipo:

WebService ws = new WebService();
var result = ws.Call( x => x.Foo("bar", 1));  // x is the ws instance
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top