Журнал поймал исключения извне метод, в котором они были пойманы

У меня есть такой метод:

public TResult DoSomethingWithLogging<TResult>(Func<TResult> someAction)
{
    try
    {
        return someAction.Invoke();
    }
    catch (Exception ex)
    {
        LogException(ex)
        throw;
    }

Этот метод используется следующим образом:

var result = DoSomethingWithLogging(() => Foo());

Я также хочу регистрировать исключения, которые были перехвачены внутри Foo(). Я не могу использовать throw в catch внутри Foo

Как я могу поймать такие исключения?

Пример:

public static string Foo()
{
    try
    {
        return "Foo";
    }
    catch (Exception)
    {
        // I have to log this exception too without adding anything to Foo
        return "Exception caught";            
    }       
}
12 голосов | спросил Vladislav Kurkotov 24 22015vEurope/Moscow11bEurope/MoscowTue, 24 Nov 2015 15:02:44 +0300 2015, 15:02:44

3 ответа


0

Вы можете привязаться к событию FirstChanceException. Вот ваш код, модифицированный для демонстрации этого:

using System;
using System.Runtime.ExceptionServices;

public class Program
{
  public static void Main()
  {
      AppDomain.CurrentDomain.FirstChanceException += 
      (object source, FirstChanceExceptionEventArgs e) =>
      {
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
          AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
      };
    Console.WriteLine("Hello World");
    Console.WriteLine(DoSomethingWithLogging(() => Foo()));
  }

  public static TResult DoSomethingWithLogging<TResult>(Func<TResult> someAction)
  {
    try
    {
      return someAction.Invoke();
    }
    catch (Exception ex)
    {
      Console.WriteLine(ex.Message);
      throw;
    }
  }

  public static string Foo()
  {
    try
    {
      throw new Exception("This will be caught");
      return"Foo";
    }
    catch (Exception) //I have to log this exception too without adding anything too Foo
    {
      return "Exception caught";      
    }    
  }
}

Как правило, я буду очень осторожен с этим в любых ситуациях, кроме сценариев отладки. Как только он пойман, он не должен рассматриваться как исключение по коду выше. (Конечно, поймать его в первую очередь могло бы быть логической ошибкой, поэтому это действительно имеет определенную ценность в сценариях отладки).

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

ответил Jon Hanna 24 22015vEurope/Moscow11bEurope/MoscowTue, 24 Nov 2015 15:08:31 +0300 2015, 15:08:31
0

Вы можете сделать это, обрабатывая AppDomain.FirstChanceException событие :

  

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

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

ответил CodeCaster 24 22015vEurope/Moscow11bEurope/MoscowTue, 24 Nov 2015 15:05:59 +0300 2015, 15:05:59
0

Я думаю, вы поступаете неправильно. Очень плохая идея предполагать что-либо о реализации foo. (Как и JDM, упомянутый в комментариях, это запах кода, и это доставит вам неприятности)

Один из способов изменить ваш подход - использовать события

class FooClass {

   public event SkippedWorkEventHandler SkippedWork;

   public void Foo() {
      try {
       /* some code */
      } catch (Exception ex) {
         if (SkippedWork != null) {
            /* pass in the relevant data to eventargs */
            SkippedWork(this, EventArgs.Empty)
         }
      }
   }

  public void DoSomethingWithFoo() {
     SkippedWork += new LogSkippedWorkEventHandler 

     try {
        Foo() 
     } catch (Exception ex) {
       /*handle uncaughed exceptions here */
     }

  }
}

Причина этого в том, что снаружи я не гарантирую, что использую try /catch для обнаружения того, что происходит внутри foo. Я мог бы переписать его на простой, если проверить и вернуться, если мой тест не пройден. Результат foo будет таким же, за исключением того, что теперь ваши исключения не регистрируются.

Объявляя событие, вы позволяете любому из присутствующего, кто интересуется определенными вещами (пропущенная строка на основе вашего комментария), реагировать на него. и вы заключили контракт, в котором говорилось, что вы будете соблюдать /поднимать это событие.

ответил Batavia 24 22015vEurope/Moscow11bEurope/MoscowTue, 24 Nov 2015 15:50:10 +0300 2015, 15:50:10

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132