Использование DSL для генерации кода C#

В настоящее время проект, с которым я работаю, не имеет полностью фиксированных моделей (из-за внешнего влияния), и поэтому я хотел бы иметь некоторую гибкость в их написании. В настоящее время они реплицируются на трех разных уровнях приложения (db, web api и client), и каждый из них имеет аналогичную логику (т. е. утверждение.)

Мне было интересно, есть ли подход, который позволит мне написать файл модели (скажем, в ruby), а затем преобразовать эту модель в необходимую файлы c#. В настоящее время кажется, что я просто пишу много шаблонного кода, который может измениться на любом этапе, тогда как этот сгенерированный подход позволит мне сосредоточиться на гораздо более важных вещах.

есть ли у кого-нибудь рекомендация для чего-то подобного, dsl/язык, на котором я могу это сделать, и есть ли у кого-нибудь опыт в отношении чего-то подобного?

3 ответов


Это можно легко сделать с ANTLR. Если выходные данные достаточно похожи, вы можете просто использовать механизм шаблонов текста-в противном случае он может создать абстрактное синтаксическое дерево для вас.


Я видел систему, которая использовала частичные классы и частичные методы для регенерации кода, не влияя на пользовательский код. "Механизм правил", если хотите, был полностью сгенерирован из диаграммы состояния Visio. Это в основном плохой рабочий процесс mans, но очень легко изменить. Диаграмма Viso была экспортирована в XML, который был прочитан с помощью powershell и T4 для создания классов.

приведенный выше пример внешнего DSL. Внешний по отношению к языку программирования, который приложение запускается. С другой стороны, вы можете создать внутренний DSL, который реализован и используется на языке программирования.

этот и предыдущие статья о DSLSs из Code-Magazine довольно хороши.

В приведенной выше ссылке Нил Форд показывает вам, как создать внутренний DSL на C# используя интерфейс.

одна вещь, которую он еще не упомянул, заключается в том, что вы можете поместить этот атрибут [EditorBrowsable(EditorBrowsableState.Никогда)] на вашем методы, чтобы они не казались intellisense. Это означает, что вы можете скрыть методы, отличные от DSL (если хотите), в классе от пользователя DSL, что делает fluent API намного более обнаруживаемым.

вы можете увидеть свободный интерфейс, написанный в прямом эфире в этой серии видео по Даниил Cazzulino при написании контейнера IoC с TDD

на тему внешних DSLs у вас также есть возможность Осло (CTP на данный момент) что вполне мощный в его способности позволить вам создавать внешние DSL, которые могут быть выполнены непосредственно, а не для использования генерации кода, которые приходят к мысли, что это не очень DSL вообще.


Я думаю, что вы на правильном пути.

то, что я обычно делаю в такой ситуации, - это создать простой язык, который фиксирует мои потребности и написать для него парсер LL1 (рекурсивный спуск).

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

Я могу либо сгенерировать структуру дерева синтаксического анализа, и сгенерировать, скажем, 3 различные виды кода из этого, или я могу просто заставить его генерировать код на лету, либо используя переменную режима с 3 значениями, либо просто одновременно писать код в 3 разных выходных файла.

есть несколько способов сделать это. Если вы боитесь писать Парсеры (как некоторые программисты), есть много других так.