Модуль инициализаторы в C # - PullRequest
23 голосов
/ 16 декабря 2009

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

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

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

Ответы [ 5 ]

10 голосов
/ 29 июня 2013

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

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

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

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

static <Module>()
{
    ModuleInitializer.Initialize();
}
8 голосов
/ 16 декабря 2009

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

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

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

3 голосов
/ 25 июля 2011

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

1 голос
/ 12 февраля 2015

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

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

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

Есть только одна проблема, которая делает ваше решение бесполезным для меня: Ваш инициализатор вызывается, когда приложение первым ДОСТУПАЕТ что-либо в сборке.

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

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

0 голосов
/ 17 декабря 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...