2012-07-05 2 views
11

나는 이것을 배우는 생산적인 방법 인 것처럼 보이지만 기존부터 단순한 응용 프로그램을 빌드하여 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() 
     { 
     } 
    } 
} 

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")); 

:


그것은 내가이 줄을 변경할 필요가 있다고 밝혀

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

     System.Windows.Forms.Timer Ticker 
     { 
     } 
    } 
} 
그러나

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

, 지금은이 출력을 얻을

이제 "get; set;을 얻지 못합니다." 속성 내의 텍스트. 아무도 내가 빠진 것을 아는가?

답변

7

속성이 추가되지 않은 이유는 Roslyn의 다른 모든 것과 마찬가지로 SyntaxList이 변경되지 않는다고 생각합니다. Add()가 업데이트 된 SyntaxList을 반환합니까? (나는 지금 이것을 검증 할 수 없다. 아직 새로운 CTP로 전환하지 않았다.)

Roslyn에서 이와 같은 코드는 매우 장황 할 수 있지만 필요 이상으로 복잡하게 만든다. 구문 트리를 아래에서 위로 빌드하면 모든 변경 후에 root을 업데이트 할 필요가 없습니다. 먼저 클래스의 멤버를 만든 다음 클래스의 멤버를 만들고 네임 스페이스를 만듭니다. 그렇게하면 모든 주석을 전혀 다룰 필요가 없습니다. 새로운 유창 API 사용

+0

귀하의 알림은 내가 아래에 게시하는 잘못을하고 있었는지 실현하기 위해 저를지도한다. 실제로 내 특정 구문 트리를 아래에서 위로 빌드하는 방법에 대한 별도의 질문을 할 것입니다. – Beaker

+0

다음은 제안한대로 신택스 트리를 처음부터 새로 만드는 방법에 대한 새로운 질문에 대한 링크입니다. http://stackoverflow.com/questions/11351977/roslyn-ctp-building-a-syntaxtree-from-the-ground-up – Beaker

+1

당신의 다른 질문에서 저는 Quoter라고 불리는 도구에 대한 링크를 추가했습니다. 모든 프로그램에 대해 Roslyn 구문 API 호출을 자동으로 생성 : http://blogs.msdn.com/b/kirillosenkov/archive/2012/07/22/roslyn-code-quoter-tool-generating-syntax-tree-api- calls-for-any-c-program.aspx –

5

(.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)))));