C# 修改语法树,然后得到更新的语义模型

C# 修改语法树,然后得到更新的语义模型,c#,roslyn,C#,Roslyn,我试图修改语法树,然后更新语义模型。以下是我到目前为止的情况: var tree = Roslyn.Compilers.CSharp.SyntaxTree.ParseCompilationUnit(code); var compilation = Roslyn.Compilers.CSharp.Compilation.Create( "MyCompilation", syntaxTrees: new[

我试图修改语法树,然后更新语义模型。以下是我到目前为止的情况:

var tree = Roslyn.Compilers.CSharp.SyntaxTree.ParseCompilationUnit(code);
var compilation = Roslyn.Compilers.CSharp.Compilation.Create(
                        "MyCompilation",
                        syntaxTrees: new[] { tree },
                        references: new[] { mscorlib });
var semanticModel = compilation.GetSemanticModel(tree);
...
var oldStatementNode = (parent as ExpressionStatementSyntax); //some SyntaxNode in the tree
var oldExpressionNode = oldStatementNode.Expression;
var newExpressionNode = Syntax.ParenthesizedExpression(oldExpressionNode);
var newRootNode = tree.GetRoot().ReplaceNode(oldExpressionNode, newExpressionNode);

var semanticInfo = semanticModel.GetTypeInfo(newExpressionNode); //throws exception "Syntax node is not within syntax tree"
如果我尝试调用
semanticModel=compilation.GetSemanticModel(tree)GetTypeInfo()
之前,可以使用
树进行新编译,甚至可以进行新编译-相同的异常

那么如何更新语义模型呢? (当然,我可以修改源代码并从一开始就用它做所有事情,但我想还有更有效的方法)


我肯定这里遗漏了一些明显的东西,也许在某处创建了一个新的语法树?

Roslyn类型是不可变的,因此您需要为您的
newRootNode
构建一个新的
SyntaxTree
,然后调用
compilation.UpdateSyntaxTree
以获得新的
编译,然后可以调用
newcommpilation.GetSemanticModel(newTree)
来获取新的
SemanticModel

考虑升级到服务级别并使用隔离。比如:

var doc = Solution.Create(SolutionId.CreateNewId()).AddCSharpProject("MyCompilation", "MyCompilation").AddMetadataReference(mscorlib).AddDocument("MyFile", code);

var semanticModel = (SemanticModel)doc.GetSemanticModel();
var root = (CompilationUnitSyntax)doc.GetSyntaxRoot();

SyntaxNode parent = null;
var oldStatementNode = (parent as ExpressionStatementSyntax); //some SyntaxNode in the tree
var oldExpressionNode = oldStatementNode.Expression;
var newExpressionNode = Syntax.ParenthesizedExpression(oldExpressionNode);
var newRootNode = root.ReplaceNode(oldExpressionNode, newExpressionNode);

doc = doc.UpdateSyntaxRoot(newRootNode);
semanticModel = (SemanticModel)doc.GetSemanticModel();