Question

Je souhaite créer un générique auquel je peux transmettre une fonction en tant que paramètre. Toutefois, cette fonction peut inclure des paramètres elle-même, de manière à ce que ...

int foo = GetCachedValue("LastFoo", methodToGetFoo)

Tels que:

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

Je veux essentiellement une méthode qui vérifie le cache pour une valeur, sinon elle va générer la valeur en fonction de la méthode transmise.

Pensées?

Était-ce utile?

La solution

On dirait que vous voulez 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;
}

L’appelant peut ensuite envelopper le message de différentes façons. pour des fonctions simples:

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

ou lorsque des arguments sont impliqués, une fermeture:

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

Autres conseils

Utilisation de System.Action et de l'expression lambda (méthode anonyme). Par exemple

    public void myMethod(int integer){

    //Do something

}

public void passFunction(System.Action methodWithParameters){

    //Invoke
    methodWithParameters();

}

//...

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

Vous pouvez créer votre propre délégué, mais en C # 3.0, il peut s'avérer plus pratique d'utiliser la famille de délégués Func<T> intégrée pour résoudre ce problème. Exemple:

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
}

Cette méthode prendra trois arguments: une chaîne, un int et une fonction qui prend un DateTime et retourne un int. Par exemple:

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

Différents types Func<T, U, V...> etc. existent dans le cadre pour prendre en charge les méthodes avec différentes quantités d'arguments.

Créer un délégué pour la méthode methodToGetFoo

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

Définissez GetCachedValue pour utiliser le délégué

int GetCachedValue(string key, GenerateValue functionToCall);

Ensuite, dans l'implémentation de OnGenerateValue, vous pouvez vérifier les paramètres.

Voici quelque chose de simple, j'ai commencé cela peut être poussé un peu plus loin (comme je l’ai fait pour un projet commercial).

Dans mon cas, cela consistait à mettre en cache les appels de service Web et a été utilisé comme suit:

WebService ws = new WebService();
var result = ws.Call( x => x.Foo("bar", 1));  // x is the ws instance
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top