Использование DSL для генерации кода C # - PullRequest
6 голосов
/ 19 марта 2009

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

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

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

Ответы [ 3 ]

5 голосов
/ 21 марта 2009

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

5 голосов
/ 19 марта 2009

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

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

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

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

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

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

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

1 голос
/ 21 марта 2009

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

Что я обычно делаю в такой ситуации, так это проектирую простой язык, который отражает мои потребности, и для него пишу парсер LL1 (Recursive Descent).

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

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

Есть несколько способов сделать это. Если вы боитесь писать синтаксические анализаторы (как это делают некоторые программисты), в SO есть много другой помощи.

...