Статья расскажет о фиче, которая появилась в 2020 году для Visual Studio. Дословно фича называется "Source Generators" или кодогенерация. Как утвердждает Microsoft, данная фича должна дать больше свободы при проведении дополнительных модификаций компилируемого приложения. Статья расскажет об основных понятиях, которые используют кодогенераторы и покажет, как можно создать простой генератор исходных кодов. Также рассмотрит проекты, которые успешно эту фичу используют для решения практических проблем.

Кодогенерация

Сам по себе процесс создания дополнительного кода "на лету" - довольно старая идея, однако разработчики Visual Studio решили сделать эту фичу доступной для разработчиков на языке программирования C#. Вообще данный прием известен в языках программирования как метапрограммирование. Кстати, согласно документу о кодогенераторах, именно метапрограммирование на С# и есть цель создания данной фичи.

Для использования функции потребуется как минимум Visual Studio 2019 и выше, а так же .NET 5 Preview и выше.

Хоть и прошло уже больше года, фича все еще имеет свои недостатки и ей стоит пользоваться с должным уровнем контроля. Автоматическая генерация кода - это вовсе не значит правильное и безопасное создание программного обеспечения. Фича работает во время компиляции. Можно расценивать её как дополнительный этап кастомной команды для компиляции, но в этой функции можно создавать дополнительные классы, интерфейсы для уже существующих библиотек.

Так как довольно сложно просто представить, для чего это чудо-изобретение вообще можно использовать, сами разработчики из Microsoft рекомендуют работать с фичей исходя из следующих правил:

  1. Кодогенераторы хороши для:

    • ускорения создания web приложений

    • работы с сериализацией

    • работы с командной строкой

    • работы с инструментами вроже SWIG

  2. Кодогенераторы плохи для изменения любого уже созданного кода, а это значит никаких:

    • изменений несовершенств языка программирования

    • оптимизаций

    • добавлений механизмов логгирования

    • модификаций промежуточного кода IL

    • модификаций алгоримта приложения, в том числе изменения соглашения о вызовах функций

Так же Microsoft позиционирует данную фичу как инструмент для работы с NuGet пакетами.

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

Немного практики

Создать генератор кода можно по нескольким примерам, которые доступны в сети. Если мы хотим создать код заново, то нам стоит иметь в виду, что кодогенераторы могут поставляться только как библиотека, соответственно придется выбирать именно этот типи проекта. Так же для создания генератора придется выполнить следующий алгоритм:

  1. Выбор типа проекта

  2. Настройка проекта для кодогенерации

  3. Написание генератора

  4. Использование генератора в проекте

Для 100% работоспособности функции кодогенерации лучше использовать версию .NET 6.0. Для ускорения процесса создания проекта, можно использовать пример, который находится здесь.

Самый простой генератор располагается в исходном коде HelloWorldGenerator.cs. В этом файле стоит отличать части, которые относятся к коду, который работает для связывания нового кода с существующим проектом и сам код, который будет добавлен в проект. Ниже приведен фрагмент, который как раз включает код, который будет добавляться в проект на этапе компиляции:

...

StringBuilder sourceBuilder = new StringBuilder(@"
using System;
namespace HelloWorldGenerated
{
    public static class HelloWorld
    {
        public static void SayHello() 
        {
            Console.WriteLine(""Hello from generated code!"");
            Console.WriteLine(""The following syntax trees existed in the compilation that created this program:"");
");
...

Как видно из конструкции, это пока что просто строка, которая включает обычный исходный код. Чтобы этот код использовать, в итоге нужно будет просто из приложения, которое будет использовать нашу библиотеку, вызвать нужный класс и метод. Примерно вот так:

...
 HelloWorldGenerated.HelloWorld.SayHello();
 ...

Кстати, если нет желания настраивать окружение полностью, можно протестировать фичу прямо онлайн вот здесь.

На первый взгляд это не очень полезный пример, но можно использовать генерацию и для более масштабных действий. Например, можно воспользоваться пакетом CsWin32. Этот проект используется для того чтобы быстрее и проще взаимодействовать из C# с нативными WinAPI функциями. Кодогенераторы здесь занимаются автоматической генерацией оберток для функций, которые помещаются в файл NativeMethods.txt.


Также я хочу пригласить всех на бесплатный вебинар про новые версии C#, который пройдет в OTUS 24 января. На вебинаре обсудим ключевые нововведения релиза .NET 6.0 с C# 10, а также познакомимся с полезными и часто используемыми новшествами последних версий языка C#.

Регистрация доступна по ссылке.

Комментарии (3)


  1. dopusteam
    12.01.2022 19:35
    +5

    Ужасная статья. Неужели нельзя было до ума довести?


  1. kuduh
    12.01.2022 23:42
    +3

    А начиналось все так хорошо. Такое ощущение что автор передумал писать статью)))


  1. VaalKIA
    13.01.2022 05:12
    +1

    Я просто оставлю это здесь:

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

    Кодогенерация — часть процесса компиляции, когда специальная часть компилятора, кодогенератор, конвертирует синтаксически корректную программу в последовательность инструкций, которые могут выполняться на машине.

    Статью, видимо, писал очень крутой «кодер».