簡體   English   中英

使用 Roslyn 將班級成員添加到特定位置?

[英]Adding class members into specific locations using Roslyn?

我正在使用ClassDeclarationSyntax.AddMembers()向類添加方法。 該方法出現在類中,但我想知道如何將方法添加到特定位置。 到目前為止,它們被添加到類末尾的#if指令中。

羅斯林版本:4.4.0

運行代碼:

var tree = CSharpSyntaxTree.ParseText(@"
namespace Test
{
public class A
{
#if !SILVERLIGHT
public int someField;
#endif
}
}");

var classNode = tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>().First();

var previousWhiteSpacesToken =
    SyntaxFactory.Token(SyntaxTriviaList.Empty, SyntaxKind.None, SyntaxTriviaList.Empty);

var method = SyntaxFactory.MethodDeclaration( //
        SyntaxFactory.PredefinedType( //
            SyntaxFactory.Token(SyntaxKind.IntKeyword)), "CalculateSize") //
    .WithModifiers(SyntaxTokenList.Create(previousWhiteSpacesToken)
        .Add(SyntaxFactory.Token(SyntaxKind.PublicKeyword))) //
    .WithBody(SyntaxFactory.Block()).NormalizeWhitespace();

var newClassNode = classNode.AddMembers(method).NormalizeWhitespace();
Console.WriteLine(newClassNode.ToString());

會得到這樣的結果:

public class A
{
#if !SILVERLIGHT
    public int someField;
    public int CalculateSize()
    {
    }
#endif
}

我知道有辦法做到這一點,但這個結果只能保證正確性:

public class A
{
    public int CalculateSize()
    {
    }
#if !SILVERLIGHT
    public int someField;
#endif
}

我期待這個結果:

public class A
{
#if !SILVERLIGHT
    public int someField;
#endif
    public int CalculateSize()
    {
    }  
}

這里的問題是#endif是關閉類聲明的}的主要瑣事。 因此,當您只添加一個成員時, #endif仍然是}的主要瑣事。

您需要做的是將}的主要瑣事移動為您要添加的新方法的主要瑣事。

這是您的代碼的修改版本:

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

var tree = CSharpSyntaxTree.ParseText(@"
namespace Test
{
public class A
{
#if !SILVERLIGHT
public int someField;
#endif
}
}");

var classNode = tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>().First();

var previousWhiteSpacesToken =
    SyntaxFactory.Token(SyntaxTriviaList.Empty, SyntaxKind.None, SyntaxTriviaList.Empty);

var method = SyntaxFactory.MethodDeclaration( //
        SyntaxFactory.PredefinedType( //
            SyntaxFactory.Token(SyntaxKind.IntKeyword)), "CalculateSize") //
    .WithModifiers(SyntaxTokenList.Create(previousWhiteSpacesToken)
        .Add(SyntaxFactory.Token(SyntaxKind.PublicKeyword))) //
    .WithBody(SyntaxFactory.Block())
    .WithLeadingTrivia(classNode.CloseBraceToken.LeadingTrivia).NormalizeWhitespace(); // copy '}' leading trivia to the new method.

// remove leading trivia from '}', they are moved previously to the new method.
var newClassNode = classNode.WithCloseBraceToken(classNode.CloseBraceToken.WithLeadingTrivia()).AddMembers(method).NormalizeWhitespace();
Console.WriteLine(newClassNode.ToString());

這將打印以下內容(正是您的期望):

public class A
{
#if !SILVERLIGHT
    public int someField;
#endif
    public int CalculateSize()
    {
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM