2009-08-25 3 views
10

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

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

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

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

ответ

3

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

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

Вам все равно понадобится некоторая обработка ошибок на вызывающем абоненте, если экземпляр вернет вам первое (или второе и т. Д.) Время.

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

например

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

Это на самом деле то, что у меня есть сейчас, за исключением того, что я использую какую-то двойную проверенную блокировку, а мой' _initialized' bool 'volatile' (не должен необходимо без двойной проверки блокировки) – Thorarin

3

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

+0

MSDN упоминает, что тип останется неинициализированным, но я не сразу понял, что было бы невозможно создать экземпляр. Я бы ожидал более явного предупреждения об этом. Не так много работы, но он делает статические конструкторы намного менее полезными :( – Thorarin

+0

@Thorarin - только для жизни AppDomain. 'Type останется неинициализированным для времени жизни домена приложения, в котором работает ваша программа 'из MSDN http://msdn.microsoft.com/en-us/library/k9x6w0hc.aspx – VoodooChild

0

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