mROA.CodegenTools

Как робин для RPC-бэтмена

Чтож, если говорить о кодгене в C# при помощи Roslyn, то тут все не так шикарно, как могло бы быть в других областях программировании. Ну по крайне мерее официально по примерам от Microsoft предлагается использовать просто интерполяцию строк.


// Build up the source code
var code = $@"// 

using System;
using System.Collections.Generic;

namespace {namespaceName};

partial class {className}
{{
    public IEnumerable Report()
    {{
{string.Join("\n", methodBody)}
    }}
}}
";

// Add the source code to the compilation.
context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8));
    

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

Синтаксис mROA.CGT шаблонов основан на супер упрощенной, версии xml из параллельной вселенной и немного перекликается с шаблонами T4. Однако в отличие от T4, код исполняется по-нормальному в среде C# кода, а не как то там среди генерируемого кода.

Каждый тег в файле, который определяет так называемый "Документ", начинается с <! после чего идет тип тега, и заканчивается > . Например <!L someLinkName> . Этот тег - тег ссылки с идентификатором. При компиляции документа она попытается найти определение для своего идентификатора и вставить его содержащийся текст вместо себя.

Есть два типа тегов по окончанию: те, которые заканчиваются на своем же объявлении, например Link tag ( <!L> ), и те которые нужно закрыть таким же тегом. Таким тегом является тег определения (Define tag). Он объявляется таким же образом, как Link tag: <!D someLinkName> , но его нужно так же закрыть, используя <!D> . Между головой и хвостом тега заключается текст, который он определяет.

Например, тут тег <!D someLinkName> определяет текст "qwerty text", а <!L someLinkName> вставляет его.

<!L someLinkName><!L someLinkName><!L someLinkName>
<!D someLinkName>qwerty text<!D>

При компиляции такого документа шаблона на выходе получится qwerty textqwerty textqwerty text потому что были прописаны 3 ссылки на одно и то же определение