C# 我们应该如何向现有变量添加实例化?

C# 我们应该如何向现有变量添加实例化?,c#,roslyn,C#,Roslyn,我编写了一个分析器,可以正确地检测未实例化的集合。现在我正在编写适当的CodeFixProvider,它将提供实例化它的选项 当我执行代码并查看提供的修复程序时,它只会删除标识符并只保留类型。我的方法哪里出错了 public async Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, TextSpan span, IEnumerable<Diagnostic> diagnostics

我编写了一个分析器,可以正确地检测未实例化的集合。现在我正在编写适当的CodeFixProvider,它将提供实例化它的选项

当我执行代码并查看提供的修复程序时,它只会删除标识符并只保留类型。我的方法哪里出错了

public async Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, TextSpan span, IEnumerable<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
    var root = await document.GetSyntaxRootAsync(cancellationToken);
    var token = root.FindToken(span.Start);
    document.TryGetSemanticModel(out var semanticModel);
    var statement = token.Parent.Parent as VariableDeclarationSyntax;

    // Construct variable declaration
    var declarator = new SeparatedSyntaxList<VariableDeclaratorSyntax>();
    var identifier = statement.Variables[0].Identifier;
    var newType = semanticModel.GetTypeInfo(statement.Type).Type;
    var newObject = SyntaxFactory.ObjectCreationExpression(type: SyntaxFactory.ParseTypeName(newType.Name));
    var equalsClause = SyntaxFactory.EqualsValueClause(newObject);
    declarator.Add(SyntaxFactory.VariableDeclarator(identifier, null, equalsClause));

    var newStatement = SyntaxFactory.VariableDeclaration(statement.Type, declarator);
    var newRoot = root.ReplaceNode(statement, newStatement);

    return new[]
    {
        CodeAction.Create("Instantiate collection variable", document.WithSyntaxRoot(newRoot))
    };
}

公共异步任务GetFixesAsync(文档文档、文本span、IEnumerable诊断、取消令牌取消令牌)
{
var root=await document.GetSyntaxRootAsync(cancellationToken);
var token=root.FindToken(span.Start);
TryGetSemanticModel(out-var-semanticModel);
var statement=token.Parent.Parent作为VariableDeclarationSyntax;
//构造变量声明
var声明符=新的SeparatedSyntaxList();
变量标识符=语句。变量[0]。标识符;
var newType=semanticModel.GetTypeInfo(statement.Type).Type;
var newObject=SyntaxFactory.ObjectCreationExpression(类型:SyntaxFactory.ParseTypeName(newType.Name));
var equalsClause=SyntaxFactory.EqualsValueClause(新对象);
Add(SyntaxFactory.VariableDeclarator(标识符,null,equalsClause));
var newStatement=SyntaxFactory.VariableDeclaration(statement.Type,declarator);
var newRoot=root.ReplaceNode(语句,newStatement);
返回新的[]
{
Create(“实例化集合变量”,document.WithSyntaxRoot(newRoot))
};
}

您必须记住,Roslyn中的所有类型都是不可变的。这意味着,即使像
Add()
这样的操作实际上也不会修改调用它们的对象,而是返回修改过的对象

这意味着在
Add()
之后,必须使用返回的值,而不是原始对象

如果您将代码修改为以下内容,它将起作用:

declarator = declarator.Add(SyntaxFactory.VariableDeclarator(identifier, null, equalsClause));

干杯,这似乎奏效了。我没有看到预览窗口中弹出的更改,但这可能是因为添加的代码无效:现在它被添加为
List ident=newList。是否有任何方法可以轻松获得包含泛型类型的默认构造函数,或者我是否必须显式构造
[space]List()
?@jeroenvanevel AFAIK,当您想要使用Roslyn生成一些代码时,从来没有一种简单的方法,您始终必须逐段创建整个语法节点。您始终可以使用SyntaxFactory.ParseExpression(“new List()”)让解析器为您构建语法节点。@MattWarren:,感谢您的建议。如果我要尝试用syntaxnodes来拼图的话,会更混乱。