Инициализаторы модулей в С#
Инициализаторы модулей - это функция CLR, которые не доступны непосредственно на С# или VB.NET. Они представляют собой глобальные статические методы с именем .cctor
, которые гарантированно выполняются до того, как будут выполнены другие коды (инициализаторы типов, статические конструкторы) в сборке. Недавно я хотел использовать это в проекте, и взломал собственное решение (консольная программа/задача msbuild), используя Mono.Cecil, но мне было интересно
-
Есть ли способ обмануть компилятор С# в интерпретаторе интеллектуального модуля? Любые атрибуты (например, CompilerGenerated, SpecialName) или другие обманки, которые могут быть использованы?
-
Использует ли С#/VB.NET когда-либо эти инициализаторы для какой-либо цели? Из того, что я видел, они используются управляемым С++ для некоторых целей взаимодействия, но я не мог найти ссылки на них, которые используются для других целей. Любые идеи?
Ответы
Ответ 1
Нет, нет возможности испускать их на С#, потому что С# помещает все в класс /struct, а инициализаторы модулей должны быть глобальными.
Вам нужно будет использовать другой инструмент для их записи, предпочтительно IL-Assembler.
Что касается второго вопроса, я должен признать, что я не знаю, но я никогда не видел никаких сгенерированных С#, и я часто использую ILDasm, поэтому я предполагаю, что он не испускает их.
Ответ 2
Посмотрите на модуль инициализатора дополнения к удивительному проекту IL-Weaver с открытым исходным кодом " fody ", написанному Саймоном Кроппом: https://github.com/fody/moduleinit
Это позволяет вам указать метод, который будет переведен в инициализатор сборки fody:
public static class ModuleInitializer
{
public static void Initialize()
{
//Init code
}
}
получает это:
static <Module>()
{
ModuleInitializer.Initialize();
}
Ответ 3
Возможно, пространство имен System.Reflection.Emit
может вам помочь. MethodAttributes
перечисление содержит аналогичные элементы (SpecialName, RTSpecialName)
.
Ответ 4
Эйнар,
Ваш вопрос не дал мне понять, что вы уже написали инструмент, который позволяет вставлять инициализатор модуля в уже скомпилированную сборку.
http://einaregilsson.com/module-initializers-in-csharp
Я попробовал ваше приложение, и оно отлично работает.
Когда вы пишете, он должен работать со всеми текущими фреймворками от 2 до 4.5.
Есть только одна проблема, которая делает ваше решение бесполезным для меня:
Инициализатор вызывается, когда приложение сначала ДОСТУПНО к чему-либо в сборке.
Мне нужно, чтобы инициализатор модуля сразу вызывался, когда сборка загружена в процесс. Но это не так. Поэтому, если приложение не получает доступ к сборке, оно никогда не будет инициализировано.
После изучения целого дня мне кажется, что единственный способ получить это - написать Managed С++ Assembly и выполнить код в DllMain().
Ответ 5
Если у вас есть статические конструкторы или одноэлементные классы, к которым вы можете получить доступ, то статическая переменная С# компилятор выдает .cctor.