Pergunta

Eu quero criar um genérico para que eu possa passar uma função como um parâmetro, no entanto esta função pode incluir parâmetros em si tão ...

int foo = GetCachedValue("LastFoo", methodToGetFoo)

Tal que:

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

Essencialmente eu quero ter um método que irá verificar a cache para um valor, caso contrário, irá gerar o valor com base no passado no método.

Os pensamentos?

Foi útil?

Solução

Parece que você quer um 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;
}

O chamador pode, em seguida, enrole isso de várias maneiras; para funções simples:

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

ou em que argumentos estão envolvidos, um fechamento:

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

Outras dicas

Usando System.Action e expressão lambda (método anonimous). Por exemplo

    public void myMethod(int integer){

    //Do something

}

public void passFunction(System.Action methodWithParameters){

    //Invoke
    methodWithParameters();

}

//...

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

Você pode criar seu próprio delegado, mas em C # 3.0 você pode achar que é mais conveniente usar o built-in Func<T> família delegado para resolver este problema. Exemplo:

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
}

Este método vai levar três argumentos: uma corda, um int, e uma função que leva um DateTime e retorna um int. Por exemplo:

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

Existem diferentes Func<T, U, V...> etc. tipos no quadro para acomodar métodos com diferentes quantidades de argumentos.

Criar um delegado para o methodToGetFoo método

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

Definir GetCachedValue usar o delegado

int GetCachedValue(string key, GenerateValue functionToCall);

Em seguida, na implementação de OnGenerateValue você pode verificar do param.

Aqui é algo simples Comecei que pode ser levado um pouco mais longe (como eu fiz para um projeto comercial).

No meu caso isso era para chamadas de serviço Web Cache, e foi usado algo como:

WebService ws = new WebService();
var result = ws.Call( x => x.Foo("bar", 1));  // x is the ws instance
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top