Предположим, у меня есть класс с 3 конструкторами, конструктор по умолчанию (без аргументов), параметризованный конструктор и статический конструктор. нравится:
public MyClass() { ... }
public MyClass(string arg) : this() { ... }
static MyClass() { ... }
Предположим, я вызываю параметризованный конструктор, в каком порядке эти конструкторы выполняются?
Я думал, что он статический, затем параметризованный, затем по умолчанию. Но ... мой опыт с этим не согласен.
Предыстория: у меня есть приложение, которое встраивает в качестве ресурса указанную DLL. Во время выполнения приложение регистрирует распознаватель сборок через
static MyClass()
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolver);
}
где метод Resolver определяется следующим образом:
static System.Reflection.Assembly Resolver(object sender, ResolveEventArgs args)
{
....
}
Я понял, что Resolver может производить сборку любым способом, который он чертовски выбирает. В случае с моим приложением он выполняет
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 перед запуском статического конструктора. Может, это могло бы быть? привести к ошибке Fusion?
у кого-нибудь есть понимание?
Это не очень важная проблема, потому что я могу перепроектировать класс, чтобы избежать этой проблемы, удалив все переменные экземпляра, которые зависят от встроенной сборки. Но я бы хотел это понять.