Как вставить код CIL в С#

Можно ли вставить код IL в метод С#?

Ответы

Ответ 2

Я только что опубликовал утилиту, которая позволяет автоматически заменять целые тела функций С# на встроенный IL, используя пользовательский атрибут. Как и в случае с аналогичными утилитами, это работает через двустороннюю передачу ILDASM/ILASM, которую можно настроить как этап после сборки. Инструмент также настраивает PDB, чтобы сохранить пошаговые настройки и установку точек останова для отдельных инструкций IL в отладчике. Он отличается от некоторых других встроенных IL-циклов тем, что он (только) заменяет целые функциональные тела, например:

    class MyClass
    {
        [ILFunc(@"
    .locals init ([0] int32 i_arg)
        ldc.i4.3
        ret
    ")]
        int MyFunc(int i_arg)
        {
            return 3;
        }
    };

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

Полный исходный код находится по адресу http://www.glennslayden.com/code/c-sharp/inline-il.

Ответ 3

Если inline IL (в том же духе встроенной сборки, поддерживаемой компиляторами C и С++), является тем, что вы ищете, это может быть достигнуто с помощью компиляции с обратной компиляцией.

Майк Столл когда-то писал инструмент для этого, насколько я знаю, он достаточно зрелый:

Кроме этого, вы можете использовать F #, который поддерживает Inline IL.

Ответ 4

Необходимый инструмент называется Cecil и является частью проекта Mono.

Вы можете получить дополнительную информацию об этом здесь: http://www.mono-project.com/Cecil

Процитировано на веб-сайте выше:

Cecil - это библиотека, написанная Jb Evain (http://evain.net/blog/) для создания и проверки программ и библиотек в формате ECMA CIL. Он имеет полную поддержку дженериков и поддерживает некоторый формат отладочного символа.

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

Ответ 5

DynamicMethod - это легкий способ выполнить это во время выполнения.

Компилятор Microsoft С# не поддерживает инъекцию IL во время компиляции, но инструмент для кодового ткачества может сделать это как шаг после компиляции.

Ответ 6

Я добавлю свой собственный инструмент в список решений, уже предоставленных здесь: InlineIL.Fody.

При этом используется ткацкий инструмент сборки Fody для изменения сборки во время сборки. Это означает, что все, что вам нужно сделать, это установить пакет NuGet, добавить файл конфигурации в ваш проект, и все готово.

Затем вам предоставляется простой и безопасный для типов API для генерации инструкций IL, который вы можете смешивать с кодом С#. Я считаю, что писать IL таким способом проще, чем писать текст, и это также удобнее, чем ILGenerator поскольку каждый код операции получает свой собственный метод только с соответствующими перегрузками.

Вот пример с using static InlineIL.IL.Emit; :

public static void ZeroInit<T>(ref T value)
    where T : struct
{
    Ldarg(nameof(value));
    Ldc_I4_0();
    Sizeof(typeof(T));
    Unaligned(1);
    Initblk();
}

Это показывает, как получить доступ к инструкции initblk которую С# в настоящее время не предоставляет.