12

私は 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
        {
        }
    }
}

今、私は「get; set;」を取得していません。プロパティ内のテキスト。誰かが私が欠けているものを知っていますか?

4

2 に答える 2

7

プロパティが追加されなかった理由はSyntaxList、Roslyn の他のすべてのものと同様に、 s が不変だからだと思います。Add()更新されたを返しませんSyntaxListか? (今は確認できません。まだ新しい CTP に切り替えていません。)

Roslyn でのこのようなコードは非常に冗長になる可能性がありますが、必要以上に複雑になっています。ボトムアップで構文ツリーを作成する場合は、変更のたびに更新する必要はありませんroot。最初にクラスのメンバーを作成し、次にクラスを作成し、次に名前空間を作成します。これを行うと、すべての注釈をまったく処理する必要がなくなります。

于 2012-07-05T08:03:38.643 に答える
7

新しい流暢な 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)))));
于 2013-06-16T20:14:48.430 に答える