【发布时间】:2020-10-28 05:48:49
【问题描述】:
用例
在运行时了解哪些#define 符号用于构建C# 应用程序会很有帮助。由于实际上似乎不可能做到这一点,因此我改为使用 Roslyn 生成一个巨大的string[],每个#define 我可能有兴趣列出。每个#define 都应作为string 文字存储在此数组中,仅当关联符号为#defined 时才包含它本身,如下所示:
// This class is generated, do not change it manually.
public static class DefineSymbols
{
public static System.Collections.Generic.IReadOnlyList<string> Symbols => _symbols;
private static readonly string[] _symbols = new string[] {
#if DEBUG
"DEBUG",
#endif
#if UNITY
"UNITY",
#endif
#if UNITY_ASSERTIONS
"UNITY_ASSERTIONS",
#endif
// ...and lots more symbols...
};
}
问题
最简单的部分是生成一个包含string 字面量的大数组。困难的部分是正确放置逗号。使用此代码...
private SyntaxNode CreateSymbolsArray(SyntaxGenerator generator, string[] defines)
{
var stringType = generator.TypeExpression(SpecialType.System_String);
return generator.FieldDeclaration(
name: "_symbols",
type: generator.ArrayTypeExpression(stringType),
accessibility: Accessibility.Private,
modifiers: DeclarationModifiers.Static | DeclarationModifiers.ReadOnly,
initializer: generator.ArrayCreationExpression(
generator.TypeExpression(SpecialType.System_String),
defines.Select(d => CreateDefine(generator, d))
)
);
}
private SyntaxNode CreateDefine(SyntaxGenerator generator, string define)
{
var @if = SyntaxFactory.IfDirectiveTrivia(SyntaxFactory.ParseExpression(define), true, true, true);
var @endif = SyntaxFactory.EndIfDirectiveTrivia(true);
return generator.LiteralExpression(define)
.WithLeadingTrivia(SyntaxFactory.Trivia(@if))
.WithTrailingTrivia(SyntaxFactory.Trivia(@endif))
;
}
...将逗号放在#if/#endif 对之外,因此除非定义了每个测试符号,否则生成的代码将无法编译。
private static readonly string[] _symbols = new string[] {
#if DEBUG
"DEBUG"
#endif
,
#if UNITY
"UNITY"
#endif
,
#if UNITY_ASSERTIONS
"UNITY_ASSERTIONS"
#endif
// ...and lots more symbols...
};
所以,这是我的问题:我怎样才能确保逗号包含在 #if/#endif 对中,就像 string 文字一样?
【问题讨论】:
-
您要解决的问题是什么?为什么和罗斯林在一起?为什么不用 t4 脚本?
-
如何使用
List<string>,并为每个符号在#if-#endif 之间生成一个list.Add("literal");? -
@LegacyCode 所有这些代码都存在于由 Roslyn 提供支持的现有代码生成器的插件中。
-
@PeterB 除非我对您的建议有什么不明白的地方,否则这就是我正在做的事情(但使用 LINQ)。
-
我的意思是这样的:
private static readonly string[] _symbols = GetSymbols();后跟一个方法private static string[] GetSymbols() { ... },其方法体创建一个List<string>,然后是 Roslyn 生成的#if ... list.Add("literal"); #endif块,最终返回 @ 987654342@.
标签: c# code-generation roslyn directive