Передача функции (с параметрами) в качестве параметра?
-
03-07-2019 - |
Вопрос
Я хочу создать универсальный файл, которому я могу передать функцию в качестве параметра, однако эта функция может включать в себя параметры сама по себе...
int foo = GetCachedValue("LastFoo", methodToGetFoo)
Такой , что:
protected int methodToGetFoo(DateTime today)
{ return 2; // example only }
По сути, я хочу иметь метод, который будет проверять кэш на наличие значения, в противном случае будет генерировать значение на основе переданного метода.
Мысли?
Решение
Звучит так, будто ты хочешь 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));
Другие советы
Использование System.Действие и лямбда-выражение (анонимный метод).Например
public void myMethod(int integer){
//Do something
}
public void passFunction(System.Action methodWithParameters){
//Invoke
methodWithParameters();
}
//...
//Pass anonimous method using lambda expression
passFunction(() => myMethod(1234));
Вы можете создать свой собственный делегат, но в C # 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...>
и т.д.типы существуют в фреймворке для размещения методов с разным количеством аргументов.
Создайте делегат для метода methodToGetFoo
public delegate object GenerateValue(params p);
public event GenerateValue OnGenerateValue;
Определите GetCachedValue для использования делегата
int GetCachedValue(string key, GenerateValue functionToCall);
Затем в реализации OnGenerateValue вы можете проверить параметры.
Здесь это что-то простое, с чего я начал, и что можно развить немного дальше (как я сделал для коммерческого проекта).
В моем случае это предназначалось для кэширования вызовов веб-службы и использовалось что-то вроде:
WebService ws = new WebService();
var result = ws.Call( x => x.Foo("bar", 1)); // x is the ws instance