C# 如何在roslyn中将字段声明转换为单独的自动属性? 我正在编写一个代码分析器,使用.NET编译器平台(Roslyn)进行代码修复。我需要将所有(非密封的)公共字段转换为单独的自动属性,因为我知道FieldDeclarationSyntax可以在一行中包含多个字段声明,这是基于下面前面Stackoverflow问题中的代码示例

C# 如何在roslyn中将字段声明转换为单独的自动属性? 我正在编写一个代码分析器,使用.NET编译器平台(Roslyn)进行代码修复。我需要将所有(非密封的)公共字段转换为单独的自动属性,因为我知道FieldDeclarationSyntax可以在一行中包含多个字段声明,这是基于下面前面Stackoverflow问题中的代码示例,c#,roslyn,roslyn-code-analysis,C#,Roslyn,Roslyn Code Analysis,这里讨论了多字段声明这一事实: 我要分析的示例代码如下: public int AnyNumericField = 0; public string AnyStringField = ""; // multiple field declaration sample public int field1, field2, field3 = 0; public StringBuilder sb1 = new StringBuilder(); priva

这里讨论了多字段声明这一事实:

我要分析的示例代码如下:

    public int AnyNumericField = 0;
    public string AnyStringField = "";
    // multiple field declaration sample
    public int field1, field2, field3 = 0;
    public StringBuilder sb1 = new StringBuilder();
    private void AnalyzePublicField(SymbolAnalysisContext context)
    {
        var aPublicField = (IFieldSymbol)context.Symbol;
        if ((aPublicField.DeclaredAccessibility == Accessibility.Public) && (!aPublicField.IsSealed))
        {
            var diagnostic = Diagnostic.Create(RuleCA1501, aPublicField.Locations[0], aPublicField.Name);

            context.ReportDiagnostic(diagnostic);
        }
    }
我想将代码修复程序加入其中:

    public int AnyNumericField { get; set; } = 0;
    public string AnyStringField { get; set; } = "";
    // multiple field declaration sample
    public int field1 { get; set; } = 0; 
    public int field2 { get; set; } = 0; 
    public int field3 { get; set; } = 0;
    public StringBuilder sb1 { get; set; } = new StringBuilder();
我当前的分析器代码如下:

    public int AnyNumericField = 0;
    public string AnyStringField = "";
    // multiple field declaration sample
    public int field1, field2, field3 = 0;
    public StringBuilder sb1 = new StringBuilder();
    private void AnalyzePublicField(SymbolAnalysisContext context)
    {
        var aPublicField = (IFieldSymbol)context.Symbol;
        if ((aPublicField.DeclaredAccessibility == Accessibility.Public) && (!aPublicField.IsSealed))
        {
            var diagnostic = Diagnostic.Create(RuleCA1501, aPublicField.Locations[0], aPublicField.Name);

            context.ReportDiagnostic(diagnostic);
        }
    }
我的问题是,我如何为此编写代码修复程序?我是否需要更改分析器以传递FieldDeclarationSyntax而不是field符号? 我找不到任何具体的例子来说明如何将一行多个字段声明转换成一个单独的自动属性

更新1: 到目前为止,我的理解是使用以下代码构造自动属性:

                PropertyDeclarationSyntax @propSymbol = SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName(fieldSymbol.MetadataName), memberName).AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword));

                @propSymbol = @propSymbol.AddAccessorListAccessors(
                    SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                        .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)
                        ));
                @propSymbol = @propSymbol.AddAccessorListAccessors(
                    SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
                    .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)
                    ));

PropertyDeclarationSyntax
的代码受本文启发:

在codefix中,您可以使用以下代码访问
VariableDeclarationSyntax

var diagnostic = context.Diagnostics.First();
var diagnosticSpan = diagnostic.Location.SourceSpan;
var syntaxNode = root.FindNode(diagnosticSpan);
var variableDeclarator = syntaxNode.FirstAncestorOrSelf<VariableDeclaratorSyntax>();
var variableDeclaration = variableDeclarator?.Parent as VariableDeclarationSyntax;
应转换为

public int field1 { get; set; }
public int field2 { get; set; }
public int field3 { get; set; } = 0;
而不是

public int field1 { get; set; } = 0; 
public int field2 { get; set; } = 0; 
public int field3 { get; set; } = 0;

还要注意,这种转换可能会破坏您的代码。例如,如果将字段作为
ref
out
传递,则该字段将无法更改为属性。

如何注册代码修复提供程序?好的,代码修复程序应该返回
Task
Task
。我在你提到的代码中看不到这一点。请看一下答案中链接的源代码,尤其是基类。您必须使用标准的Roslyn机制,因此
CodeFixProvider
中覆盖任务寄存器codefixAsync
,并在
上下文中注册更改。RegisterCodeFix