我有以下代码,它构建了一个Roslyn语句,该语句在内部调用Roslyn代码,但我在字符串转义方面遇到了问题。
这是代码:
var parseStatementArgument = "var statement = Syntax.ParseStatement(\"Console.WriteLine (\"Hello {0}\", parameter1);\");";
var st = Syntax.InvocationExpression(
Syntax.MemberAccessExpression(SyntaxKind.MemberAccessExpression, Syntax.IdentifierName("Syntax"), Syntax.IdentifierName("ParseStatement")))
.AddArgumentListArguments(
Syntax.Argument(Syntax.LiteralExpression(
SyntaxKind.StringLiteralExpression,
Syntax.Literal(
text: """ + parseStatementArgument + """,
value: parseStatementArgument)
)));
var variableDeclarator = Syntax.VariableDeclarator(Syntax.Identifier("statement"))
.WithInitializer(Syntax.EqualsValueClause(st));
var varStatement = Syntax.VariableDeclaration(Syntax.IdentifierName("var"), Syntax.SeparatedList(variableDeclarator));
var varStatementText = varStatement.Format().GetFormattedRoot().GetFullText() + ";";
var scriptEngine = new ScriptEngine(
new [] {
MetadataReference.Create("Roslyn.Compilers"),
MetadataReference.Create("Roslyn.Compilers.CSharp"),
MetadataReference.Create("Roslyn.Services"),
MetadataReference.Create("Roslyn.Services.CSharp")
},
new [] {
"System",
"Roslyn.Compilers.CSharp",
"Roslyn.Scripting",
"Roslyn.Scripting.CSharp",
"Roslyn.Services"
});
var session = Session.Create();
scriptEngine.Execute(varStatementText, session);
scriptEngine.Execute("Console.WriteLine (statement.Format().GetFormattedRoot().GetFullText());", session);
问题是,通过脚本引擎执行打印到控制台窗口的"语句"将丢失"Hello{0}"字符串周围的反斜杠。如果我在参数中添加双转义(additional\),Roslyn将引发有关缺少逗号的编译错误。
如何更新此代码,以便在语句变量中获得所需内容的语法正确版本?
切换到使用逐字逐句的字符串级别,然后在添加节点时添加另一个级别的转义。
类似于:
var parseStatementArgument = @"var statement = Syntax.ParseStatement(@""Console.WriteLine (""""Hello {0}"""", parameter1);"");";
var st = Syntax.InvocationExpression(
Syntax.MemberAccessExpression(SyntaxKind.MemberAccessExpression, Syntax.IdentifierName("Syntax"), Syntax.IdentifierName("ParseStatement")))
.AddArgumentListArguments(
Syntax.Argument(Syntax.LiteralExpression(
SyntaxKind.StringLiteralExpression,
Syntax.Literal(
text: "@"" + parseStatementArgument.Replace(""", """") + """,
value: parseStatementArgument)
)));
根据Kevin关于如何将字符串替换为文字的提示,我尝试了一下,发现这是一个有效的解决方案,但它引发了另一个问题。
解决方案:
var parseStatementArgument = "var statement = Syntax.ParseStatement(\"Console.WriteLine (\\\"Hello {0}\\\", parameter1);\");";
var st = Syntax.InvocationExpression(
Syntax.MemberAccessExpression(SyntaxKind.MemberAccessExpression, Syntax.IdentifierName("Syntax"), Syntax.IdentifierName("ParseStatement")))
.AddArgumentListArguments(
Syntax.Argument(Syntax.LiteralExpression(
SyntaxKind.StringLiteralExpression,
Syntax.Literal(
text: """ + parseStatementArgument + """,
value: parseStatementArgument.Replace ("\\\", "\"))
)));
现在,它正确地输出了一个语法正确且编译良好的代码片段。
它引发的问题是,为了得到正确的结果,我必须修改源字符串,而不是派生字符串。当用Roslyn重写代码或生成代码时,不可能要求两个或三个转义字符串文字来使Roslyn能够正确处理这一问题,也许这是Roslyn的问题,我希望有人能为我们提供一个适用于所有类型字符串的优雅解决方案。