Оболочка для функций с похожими, но не идентичными сигнатурами

Я использую API третьего уровня, который имеет ряд различных, но похожих объектов, связанных с HTTP, таких как:

TypeAService, TypeARequest, TypeAResponse

TypeBService, TypeBRequest, TypeBResponse

и т.п.

Шаблон для вызова всегда одинаков, что-то вроде:

myTypeXResponse = myTypeXService.SubmitRequest(myTypeXRequest);

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

myTypeXResponse = myWrapperFunction(myTypeXService.SubmitRequest, myTypeXRequest, typeof(TypeXServiceException));

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

Любая помощь с благодарностью.

2 ответа

Решение

Вы можете использовать дженерики для обработки этого:

public static T myWrapperFunction<T>(Func<T, T> func, T request)
    //where T : //some common base type, if it helps
{
    return func(request);
}

Метод, предложенный Servy для этой проблемы (с изменениями в моем последнем комментарии), в течение некоторого времени работал очень хорошо, но недавно я решил аналогичную проблему с другим подходом, используя делегаты вместо шаблонов. Я опубликую это здесь на тот случай, если кто-то может воспользоваться кодом:

public delegate bool TryAgainAfterException(Exception ex);

public void RepeatAction(Action action, TryAgainAfterException tryAgainFunction)
{
   // set up whatever logic you would use for your do-while loop here
   bool tryAgain;

   do
   {
      tryAgain = false;
      try
      {
         action();
      }
      catch (Exception ex)
      {
         if (tryAgainFunction(ex))
         {
            // the specific logic of the Exception
            // handling would go here, including:
            tryAgain = true;
         }
         else
            throw ex;
      }
   }
   while (tryAgain);
}

Теперь я могу получить свой объект ответа, заключив вызов в Action:

RepeatAction( () => { myTypeXResponse = myTypeXService.SubmitRequest(myTypeXRequest); },
              e => e.GetType() == TypeXServiceException );

На самом деле я не защищаю один метод перед другим, но я тоже хотел поделиться этим.

Другие вопросы по тегам