Можно ли изменить SyntaxTree в Roslyn и запустить отредактированный код? - PullRequest
0 голосов
/ 22 сентября 2018

Я изменяю код с помощью Roslyn, однако после изменения генерируется новый SyntaxNode, но я не могу найти способ выполнить этот новый код.Единственное, что я нашел, это получить ToString из нового Root и вызвать EvaluateAsync с новой строкой.Должен быть способ превзойти это, поскольку у меня уже есть новый скомпилированный код.

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;
}

1 Ответ

0 голосов
/ 22 сентября 2018

Методы, которые создают объект Script из дерева синтаксиса, к сожалению, являются внутренними для сборок Microsoft.

Но вам не нужно компилировать дважды - вы можете просто разобрать первый раз, а затемскомпилируйте второй раз.

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();
...