Подтвердить что ты не робот

Передача функции (с параметрами) в качестве параметра?

Я хочу создать общий, к которому я могу передать функцию в качестве параметра, однако эта функция может включать в себя сами параметры, поэтому...

int foo = GetCachedValue("LastFoo", methodToGetFoo)

Таким образом:

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

По сути, я хочу иметь метод, который будет проверять кеш для значения, иначе будет генерироваться значение, основанное на переданном методе.

Мысли?

4b9b3361

Ответ 1

Похоже, вы хотите 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;
}

Вызывающий может затем обернуть это разными способами; для простых функций:

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

или где используются аргументы, замыкание:

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

Ответ 2

Использование System.Action и лямбда-выражения (анонимный метод). Например

    public void myMethod(int integer){

    //Do something

}

public void passFunction(System.Action methodWithParameters){

    //Invoke
    methodWithParameters();

}

//...

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

Ответ 3

Вы можете создать свой собственный делегат, но в С# 3.0 вам может быть удобнее использовать встроенное семейство делегатов Func<T> для решения этой проблемы. Пример:

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
}

Этот метод будет принимать три аргумента: строка, int и функция, которая принимает DateTime и возвращает int. Например:

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

Различные типы Func<T, U, V...> и т.д. существуют в структуре для размещения методов с различным количеством аргументов.

Ответ 4

Создайте делегат для метода methodToGetFoo

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

Определить GetCachedValue для использования делегата

int GetCachedValue(string key, GenerateValue functionToCall);

Затем в реализации OnGenerateValue вы можете проверить параметры.

Ответ 5

Здесь что-то простое, что я начал, что можно сделать немного дальше (как это было для коммерческого проекта).

В моем случае это было для кэширования вызовов веб-сервисов и использовалось что-то вроде:

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