Обработка исключений инициализатора типа (статический конструктор) - PullRequest
11 голосов
/ 25 августа 2009

Я пишу сервис WCF на C #. Первоначально в моей реализации был статический конструктор, выполняющий однократную инициализацию, но некоторые из выполняемых инициализаций могут (временно) завершиться неудачей.

Похоже, что статические конструкторы вызываются только один раз, даже если первая (неудачная) попытка вызвала исключение? Любые последующие попытки создать экземпляр моего класса сразу же потерпят неудачу с TypeInitializationException без фактически выполняемого кода.

Спецификация языка C # гласит, что статический конструктор вызывается не более одного раза, но в основном это делает исключение, из-за которого возникает ошибка, которую вы не сможете исправить, даже если поймаете ее?

Я что-то здесь упускаю? Я полагаю, мне следует переместить что-нибудь удаленно опасное в конструктор экземпляра службы и вручную проверить, была ли инициализация класса уже успешно завершена ранее?

Ответы [ 3 ]

4 голосов
/ 25 августа 2009

Урок здесь довольно прост: не делайте в статическом конструкторе ничего, что могло бы дать сбой.

3 голосов
/ 25 августа 2009

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

Другой вариант - сделать это как одиночный файл - каждый раз, когда вы пытаетесь получить экземпляр, вы можете правильно создать тип, пока не добьетесь успеха, даже если он потерпит неудачу в первый раз.

Вам все равно потребуется некоторая обработка ошибок для вызывающей стороны на случай, если Instance вернет вам ноль в первый (или второй и т. Д.) Раз.

Редактировать: И если вам не нужен синглтон, просто попросите ваш конструктор экземпляра инициализировать статические части

, например

private object _lock = new object()
private bool _initialized;

public T()
{
   lock(_lock)
   {
      if(!_initialized)
      {
         try
         {
           //Do static stuff here
         }
         catch(Exception ex_)
         {
           //Handle exception
         }
      } 
   }
}
1 голос
/ 25 августа 2009

Обходной путь, который я использовал в прошлом, - создание Синглтона. Заставить статический конструктор давать сбой, если и только если сбой означает, что все приложение не может быть запущено.

...