2009-08-12 5 views
0

Предположим, у меня есть класс с 3 конструкторами, конструктор по умолчанию (без аргумента), параметризованный конструктор и статический конструктор. например:Заказ конструкторов для класса C#: параметризованный, по умолчанию и статический?

public MyClass() { ... } 
public MyClass(string arg) : this() { ... } 
static MyClass() { ... } 

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

Я думал, что это статичный, затем параметризованный, а затем по умолчанию. Но ... мой опыт не согласен с этим.

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

static MyClass() 
{ 
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolver); 
} 

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

static System.Reflection.Assembly Resolver(object sender, ResolveEventArgs args) 
{ 
    .... 
} 

я понял, что распознаватель может производить сборку, так, как это штопка хорошо выбирает , В случае моего приложения, это делает имя

Assembly.GetExecutingAssembly().GetManifestResourceStream(name); 

где это имя вложенного ресурса. Затем прочитайте все байты этого ресурса и сделайте Assembly.Load (byte []) в блоке прочитанных байтов.

Это может показаться вам странным, но это работает.

Вы могли бы сказать: Почему в мире вы бы вставляли сборку, а не только ILMerge? Хороший вопрос. Я думаю, что мне нужно внедрить, потому что встроенная сборка подписана, и у меня нет ключа для повторной подписывания объединенной сборки. Поэтому я вставляю.

Проблема заключается в следующем: предположим, что я объявляю переменную члена частного экземпляра класса, которая имеет тип, определенный во встроенной сборке. В моем случае это перечисление, и я также инициализирую значение этого перечисления.

Теперь, если статический конструктор уже запущен, тогда инициализатор этого частного члена не будет работать. Но я вижу ошибку «файл не найден» - ваша основная ошибка Fusion.

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'MyApp, Version=1.1.4.1, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c' or one of its dependencies. The system cannot find the file specified. 
File name: 'MyApp, Version=1.1.4.1, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c' 

WRN: Assembly binding logging is turned OFF. 
To enable assembly bind failure logging, set the registry value[HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1. 
Note: There is some performance penalty associated with assembly bind failure logging. 
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog]. 

Если я удалю переменную частного экземпляра, то я не получу ошибку Fusion.

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


Написав это, я думаю, что, возможно, придумал ответ на свой вопрос. Возможно, это проблема времени JIT: возможно, конструкторы экземпляров JIT'd перед запуском статического конструктора. Это может быть? приведет к ошибке Fusion?

У кого-нибудь есть понимание?

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

+0

Не совсем понятно, что вы подразумеваете под «классом» в приведенном выше, это во встроенной сборке или в классе загрузки? Это может иметь значение, поскольку у вас могут быть упорядочивающие и круговые проблемы со статическими ctors. –

+0

«класс» в коде, который я пишу, который будет потреблять типы во внешней сборке. Я не знаю, где это неясно в вопросе выше. Если бы я знал, что могу изменить Q, чтобы уточнить. – Cheeso

ответ

5

Вы правы, с точки зрения порядка.

Статический конструктор запускается сначала, а затем непараметрированный конструктор, а затем параметризованный конструктор.

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

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

+0

Да, я вижу, что на сборку ссылаются прежде, чем запускается статический конструктор. Я думаю, ты прав. Вопрос в том, ПОЧЕМУ, что случай, * только когда * переменная экземпляра использует тип, определенный во встроенной сборке? – Cheeso

+0

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

+0

Да, Рид - вот в чем проблема. Это объясняет, что я наблюдал. – Cheeso