簡體   English   中英

使用Roslyn將自動實現的屬性添加到類

[英]Adding Auto-Implemented Property to class using Roslyn

我試圖通過從頭開始構建現有但簡單的應用程序來學習Roslyn,這似乎是一種有效的方法來學習它。 無論如何,我有以下代碼:

var root = (CompilationUnitSyntax)document.GetSyntaxRoot();

    // Add the namespace
    var namespaceAnnotation = new SyntaxAnnotation();
    root = root.WithMembers(
        Syntax.NamespaceDeclaration(
            Syntax.ParseName("ACO"))
                .NormalizeWhitespace()
                .WithAdditionalAnnotations(namespaceAnnotation));
    document = document.UpdateSyntaxRoot(root);

    // Add a class to the newly created namespace, and update the document
    var namespaceNode = (NamespaceDeclarationSyntax)root
        .GetAnnotatedNodesAndTokens(namespaceAnnotation)
        .Single()
        .AsNode();

    var classAnnotation = new SyntaxAnnotation();
    var baseTypeName = Syntax.ParseTypeName("System.Windows.Forms.Form");
    SyntaxTokenList syntaxTokenList = new SyntaxTokenList()
        {
            Syntax.Token(SyntaxKind.PublicKeyword)
        };

    var newNamespaceNode = namespaceNode
        .WithMembers(
            Syntax.List<MemberDeclarationSyntax>(
                Syntax.ClassDeclaration("MainForm")
                    .WithAdditionalAnnotations(classAnnotation)
                    .AddBaseListTypes(baseTypeName)
                    .WithModifiers(Syntax.Token(SyntaxKind.PublicKeyword))));

    root = root.ReplaceNode(namespaceNode, newNamespaceNode).NormalizeWhitespace();
    document = document.UpdateSyntaxRoot(root);


    var attributes = Syntax.List(Syntax.AttributeDeclaration(Syntax.SeparatedList(Syntax.Attribute(Syntax.ParseName("STAThread")))));


    // Find the class just created, add a method to it and update the document
    var classNode = (ClassDeclarationSyntax)root
        .GetAnnotatedNodesAndTokens(classAnnotation)
        .Single()
        .AsNode();

        var syntaxList = Syntax.List<MemberDeclarationSyntax>(
                Syntax.MethodDeclaration(
                    Syntax.ParseTypeName("void"), "Main")
                    .WithModifiers(Syntax.TokenList(Syntax.Token(SyntaxKind.PublicKeyword)))
                    .WithAttributes(attributes)
                    .WithBody(
                        Syntax.Block()));
        syntaxList.Add(Syntax.PropertyDeclaration(Syntax.ParseTypeName("System.Windows.Forms.Timer"), "Ticker"));
        var newClassNode = classNode
            .WithMembers(syntaxList);

    root = root.ReplaceNode(classNode, newClassNode).NormalizeWhitespace();
    document = document.UpdateSyntaxRoot(root);

它在IDocument中輸出以下代碼。

namespace ACO
{
    public class MainForm : System.Windows.Forms.Form
    {
        [STAThread]
        public void Main()
        {
        }
    }
}

雖然看起來應該更像這樣(注意我試圖添加Timer屬性)

namespace ACO
{
    public class MainForm : System.Windows.Forms.Form
    {
    public System.Windows.Forms.Timer Ticker {get; set;}

        [STAThread]
        public void Main()
        {
        }
    }
}

而且,似乎我為這樣一個簡單的過程編寫的代碼似乎過多了。 除了我的主要問題,人們可以提供有關如何以更優雅的方式解決這個問題的建議嗎? 也許鏈接到博客,或代碼片段或什么?


事實證明我需要改變這一行:

syntaxList.Add(Syntax.PropertyDeclaration(Syntax.ParseTypeName("System.Windows.Forms.Timer"), "Ticker"));

到這一行:

syntaxList = syntaxList.Add(Syntax.PropertyDeclaration(Syntax.ParseTypeName("System.Windows.Forms.Timer"), "Ticker"));

但是,現在我得到這個輸出:

namespace ACO
{
    public class MainForm : System.Windows.Forms.Form
    {
        [STAThread]
        public void Main()
        {
        }

        System.Windows.Forms.Timer Ticker
        {
        }
    }
}

現在我沒有得到“得到;設定;” 財產內的文字。 有誰知道我錯過了什么?

我認為沒有添加屬性的原因是,與Roslyn中的其他所有內容一樣, SyntaxList是不可變的。 Add()返回更新的SyntaxList嗎? (我現在無法驗證這一點,我還沒有切換到新的CTP。)

在Roslyn中這樣的代碼可能非常冗長,但是你要使它比必要的更復雜。 如果從下到上構建語法樹,則不必在每次更改后更新root :首先創建類的成員,然后創建類,然后創建名稱空間。 如果你這樣做,你將不必處理所有的注釋。

使用新的流暢API(.With ...()方法),您現在可以使用:

Syntax.PropertyDeclaration(Syntax.ParseTypeName("int"), "MyProperty")
      .WithAccessorList(
          Syntax.AccessorList(
              Syntax.List(
                  Syntax.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                        .WithSemicolonToken(Syntax.Token(SyntaxKind.SemicolonToken)),
                  Syntax.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
                        .WithSemicolonToken(Syntax.Token(SyntaxKind.SemicolonToken)))));

暫無
暫無

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

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