Использовать метод 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);
    }
}

И обе ваши перегрузки вызывают этот метод, соответственно приводя результат, если таковой имеется

  1. Вы действительно должны func.Invoke()? Почему не просто func()?
  2. Почему не твой Invoke статические?
  3. В зависимости от того, что 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; };
}
Другие вопросы по тегам