Вопрос

Инициализаторы модулей - это функция среды CLR, которая недоступна непосредственно в C # или VB.NET.Это глобальные статические методы с именем .cctor которые гарантированно выполняются до выполнения любого другого кода (инициализаторов типов, статических конструкторов) в сборке.Недавно я хотел использовать это в проекте и взломал мое собственное решение (консольная программа / задача msbuild) использую Mono.Сесил, но мне было интересно:

  1. Есть ли какой-нибудь способ обмануть компилятор C #, чтобы он выдавал инициализаторы модулей?Любые атрибуты (например,CompilerGenerated, SpecialName) или другой трюк, который можно было бы использовать?

  2. Использует ли C # / VB.NET когда-либо сами эти инициализаторы для какой-либо цели?Из того, что я видел, они используются managed C ++ для некоторых целей взаимодействия, но я не смог найти никаких ссылок на то, что они используются для других целей.Есть какие-нибудь идеи?

Это было полезно?

Решение

Нет, в C# их невозможно создать, поскольку C# помещает все в класс/структуру, а инициализаторы модулей должны быть глобальными.

Для их написания вам придется использовать другой инструмент, желательно IL-Assembler.

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

Другие советы

Ознакомьтесь с надстройкой инициализатора модуля замечательного проекта IL-Weaver с открытым исходным кодом "фоди", написано Саймоном Кроппом: https://github.com/fody/moduleinit

Он позволяет вам указать метод, который будет преобразован в инициализатор сборки с помощью fody:

public static class ModuleInitializer
{
    public static void Initialize()
    {
        //Init code
    }
}

получает это:

static <Module>()
{
    ModuleInitializer.Initialize();
}

Может быть System.Reflection.Emit пространство имен может вам помочь. MethodAttributes перечисление содержит похожие элементы (SpecialName, RTSpecialName).

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

http://einaregilsson.com/module-initializers-in-csharp

Я попробовал ваше приложение, и оно работает отлично.Как вы пишете, это должно работать со всеми текущими фреймворками от 2 до 4.5.

Есть только одна проблема, которая делает ваше решение бесполезным для меня:Ваш инициализатор вызывается, когда приложение впервые ОБРАЩАЕТСЯ К чему-либо в сборке.

Что мне нужно, так это то, что инициализатор модуля должен вызываться немедленно, когда Сборка загружается в процесс.Но это не так.Таким образом, если приложение не получает доступа к сборке, оно никогда не будет инициализировано.

После целого дня исследований мне кажется, что единственный способ получить это - написать управляемую сборку на C ++ и выполнить код в DllMain().

Если у вас есть статические конструкторы или одноэлементные классы, к которым вы можете получить доступ true, компилятор C# со статической переменной выдаст .cctor.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top