Использовать метод func для действия также?
Я создал метод для абстрагирования функциональности try/catch. У меня есть около 30 методов, которые имеют точно такой же сценарий попробовать / поймать. Поэтому я положил это одним способом:
private T Invoke<T>(Func<T> func)
{
try
{
return func.Invoke();
}
catch (Exception ex)
{
throw LogAndThrowFaultException(ex);
}
}
Теперь большинство методов называют это так:
public IEnumerable<PingResponse> GetAllForPingRequest(PingRequest pingRequest)
{
return Invoke(() => PingResponseLogic.GetAllForPingRequest(pingRequest));
}
Моя проблема в том, что у меня есть только несколько методов, которые вызывают его без необходимости возвращать значение:
Invoke<void>(() => CustomVariableGroupLogic.Delete(customVariableGroup));
Тем не менее, я не могу использовать void
там. Invoke()
метод занимает func
, но в этом случае это должно быть action
, Я провел какое-то исследование, и, похоже, мне придется создать другое Invoke()
метод, но имейте это действие. Эти предложения были сделаны в 2009 и 2010 годах. Можно ли как-то использовать мой метод func без необходимости создания другого Invoke()
метод как Invoke2()
?
4 ответа
Одним из быстрых и грязных решений было бы добавить значение по умолчанию после вызова Delete
метод. В любом случае он будет проигнорирован, если вы не назначите результат Invoke
метод переменной. Например, следующий код демонстрирует это:
Invoke(() => {CustomVariableGroupLogic.Delete(customVariableGroup); return 0; });
Вы можете увидеть аналогичный пример, предложенный здесь,
Если у вас есть много-много таких звонков, вы можете создать модную оболочку, которая будет возвращать Func
для данного Action
, Пример:
Func<Action, Func<int>> wrap = action => () => {action(); return 0;};
Теперь вы можете
Invoke(() => wrap(() => CustomVariableGroupLogic.Delete(customVariableGroup)));
но это идет немного близко к сумасшествию лямбды
Вдохновленный pcm2:
Вы можете создать перегрузку для Invoke
, что просто берет Action
в качестве параметра используйте предложенное выше решение для вызова реализации с Func<T>
:
public void Invoke(Action action)
{
Invoke(() => {action(); return 0;});
}
теперь вы просто можете
Invoke(() => CustomVariableGroupLogic.Delete(customVariableGroup));
Не могли бы вы просто создать перегрузку вызова?
public void Invoke<T>(Func<T> func){
return (T) InvokeInternal(func);
}
public void Invoke(Action action){
InvokeInternal(action);
}
Если вы хотите, чтобы оба метода выполняли одну и ту же функцию и сохраняли ее СУХОЙ, вы можете создать такой метод:
private object InvokeInternal(System.Delegate @delegate)
{
try
{
return @delegate.DynamicInvoke();
}
catch (Exception ex)
{
throw LogAndThrowFaultException(ex);
}
}
И обе ваши перегрузки вызывают этот метод, соответственно приводя результат, если таковой имеется
- Вы действительно должны
func.Invoke()
? Почему не простоfunc()
? - Почему не твой
Invoke
статические? - В зависимости от того, что
LogAndThrowFaultException
делает, это может быть довольно плохо. Убедитесь, что стек исключений сохраняется, всегда устанавливая для внутреннего исключения значениеex
,
Но да, вам нужна вторая функция, которая возвращает void вместо T.
Вы можете обернуть действие в функцию, как это. Или вы можете создать вспомогательную функцию, которая выполняет перенос:
void Main()
{
Action<string> a = s => Console.WriteLine(s);
Invoke(() => { a(); return null; });
Invoke(s);
}
private void Invoke(Action a)
{
Invoke(() => { a(); return null; };
}