我有以下代码,它构建了一个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}"串。如果我添加双重转义(附加\到参数中,Roslyn将引发有关缺少逗号的编译错误。
我如何更新此代码以在语句变量中获得我想要的语法正确版本?
答案 0 :(得分:1)
如何切换到使用逐字字符串级别,并在添加节点时添加另一级别的转义。
类似的东西:
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)
)));
答案 1 :(得分:0)
基于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问题,我希望有人会对优雅的解决方案有所了解。适用于所有类型的字符串。