简体   繁体   English

是否可以修改Roslyn中的SyntaxTree并运行已编辑的代码?

[英]Is it possible to modify a SyntaxTree in Roslyn and run the edited code?

I am changing a code using Roslyn, however, after the change a new SyntaxNode is generated, but I am not able to find a way to execute this new code. 我正在使用Roslyn更改代码,但是,在更改SyntaxNode成了新的SyntaxNode ,但我无法找到执行此新代码的方法。 The only one I found was to get the ToString from the new Root and call EvaluateAsync with the new string. 我发现的唯一一个是从新Root获取ToString并使用新字符串调用EvaluateAsync There should be a means to outperform this, since I already have a new code already compiled. 应该有一种方法可以超越这个,因为我已经有一个已编译的新代码。

static void Main(string[] args)
{
    var expression = "System.Console.WriteLine(\"Test\")";
    var compile = CSharpScript.Create<EntityRepresentation>(expression).GetCompilation();
    var root = compile.SyntaxTrees.Single().GetRoot();

    var descentands = root.DescendantNodes().Where(n =>
    {
        if (n is ArgumentSyntax)
            return true;
        return false;
    }).ToList();

    var otherRoot = root.ReplaceNodes(descentands, (n1, n2) =>
    {
        var argumentName = Argument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal("NewValue")));
        return argumentName;
    });

    var newCode = otherRoot.ToString();

    // Faz o que estou querendo, contudo não me parece a melhor maneira
    var result = CSharpScript.EvaluateAsync(newCode).Result;
}

The methods that create a Script object from a syntax tree, are unfortunately internal to the Microsoft assemblies. 不幸的是,从语法树创建Script对象的方法是Microsoft程序集的内部方法。

But, you don't have to compile twice - you can just parse the first time, and then compile the second time. 但是,您不必编译两次 - 您可以在第一次解析,然后第二次编译。

var expression = "System.Console.WriteLine(\"Test\")";
var origTree = CSharpSyntaxTree.ParseText(expression, 
                  CSharpParseOptions.Default.WithKind(SourceCodeKind.Script));
var root = origTree.GetRoot();

// -Snip- tree manipulation

var script = CSharpScript.Create(otherRoot.ToString());
var errors = script.Compile();
if(errors.Any(x => x.Severity == DiagnosticSeverity.Error)) {
    throw new Exception($"Compilation errors:\n{string.Join("\n", errors.Select(x => x.GetMessage()))}");
}
await script.RunAsync();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM