2012-02-09 63 views
10
C#類

考慮下面的類文件中的「MyClass.cs」添加自定義屬性,使用羅斯林

using System; 

public class MyClass : Entity<long> 
{ 
    public long Id 
    { 
     get; 
     set; 
    } 

    [Required] 
    public string Name 
    { 
     get; 
     set; 
    } 

    public string Slug 
    { 
     get; 
     set; 
    } 

    public DateTime CreatedOn 
    { 
     get; 
     private set; 
    } 

    public DateTime UpdatedOn 
    { 
     get; 
     private set; 
    } 

    /* ... */ 
} 

目前,我手動創建數據合同類尋找如下:

[DataContract(Namespace = "http://example.com/", Name = "MyClass")] 
public sealed class MyClass 
{ 
    [DataMember(EmitDefaultValue = false, Name = "Id")] 
    public long Id 
    { 
     get; 
     set; 
    } 

    [DataMember(EmitDefaultValue = false, Name = "Name", IsRequired = true)] 
    public string Name 
    { 
     get; 
     set; 
    } 

    [DataMember(EmitDefaultValue = false, Name = "Slug")] 
    public string Slug 
    { 
     get; 
     set; 
    } 

    [DataMember(EmitDefaultValue = false, Name = "CreatedOn")] 
    public DateTime CreatedOn 
    { 
     get; 
     set; 
    } 

    [DataMember(EmitDefaultValue = false, Name = "UpdatedOn")] 
    public DateTime UpdatedOn 
    { 
     get; 
     set; 
    } 
} 

我d喜歡使用Roslyn重寫「MyClass.cs」,所以它看起來像我手工創建的類。目前,我有以下幾點:

using System; 
using System.IO; 
using Roslyn.Compilers.CSharp; 

internal class Program 
{ 
    private static void Main() 
    { 
     var reader = new StreamReader(@"..\..\MyClass.cs"); 
     var source = reader.ReadToEnd(); 
     var tree = SyntaxTree.ParseCompilationUnit(source); 
     var rewriter = new MyRewriter(); 
     var newRoot = rewriter.Visit(tree.Root); 
     Console.WriteLine(newRoot.Format()); 
    } 
} 

public class MyRewriter : SyntaxRewriter 
{ 
    protected override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) 
    { 
     var declaration = (TypeDeclarationSyntax) base.VisitClassDeclaration(node); 

     return ((ClassDeclarationSyntax) declaration).Update(
      declaration.Attributes, 
      Syntax.TokenList(Syntax.Token(SyntaxKind.PublicKeyword), Syntax.Token(SyntaxKind.SealedKeyword)), 
      declaration.Keyword, 
      declaration.Identifier, 
      declaration.TypeParameterListOpt, 
      null, 
      declaration.ConstraintClauses, 
      declaration.OpenBraceToken, 
      declaration.Members, 
      declaration.CloseBraceToken, 
      declaration.SemicolonTokenOpt); 
    } 

    protected override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node) 
    { 
     var typeSyntax = node.Type; 

     if (node.Identifier.ValueText == "Id") 
     { 
      typeSyntax = Syntax.IdentifierName("string"); 
     } 

     var newProperty = Syntax.PropertyDeclaration(
      modifiers: Syntax.TokenList(Syntax.Token(SyntaxKind.PublicKeyword)), 
      type: typeSyntax, 
      identifier: node.Identifier, 
      accessorList: Syntax.AccessorList(
       accessors: Syntax.List(
        Syntax.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration, 
        semicolonTokenOpt: Syntax.Token(SyntaxKind.SemicolonToken)), 
        Syntax.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration, 
        semicolonTokenOpt: Syntax.Token(SyntaxKind.SemicolonToken)) 
        ) 
       ) 
      ); 

     return newProperty; 
    } 
} 

我一直試圖找到一種方法來添加數據成員和DataContract自定義屬性MyClass的,但一直未果。如何添加自定義屬性?

+0

我的閱讀方式[這](http://social.msdn.microsoft.com/Forums/en- US/roslyn/thread/f5adeaf0-49d0-42dc-861b-0f6ffd731825)MSDN線程,我會說Roslyn不支持自定義屬性。你有沒有看到其他方面的信息? – 2012-02-09 03:24:39

+0

Roslyn確實在語法級別支持屬性,而不是語義 – 2012-02-09 03:47:49

+0

有一個AttributeDeclarationSyntax類,類和屬性都有一個屬性成員,但我找不到如何構造它的示例。您也可以使用SyntaxRewiter重寫屬性。這裏是一個[示例](http://www.mindscapehq.com/blog/index.php/2011/10/20/in-bed-with-roslyn/)如何使用它。所以我會認爲它的支持,但我可能是錯的。 – bloudraak 2012-02-09 04:34:20

回答

10

Syntax.PropertyDeclaration方法的參數之一是適用於屬性的屬性列表。像所有Syntax元素一樣,它使用靜態SyntaxFactory類中的工廠方法構建。

Roslyn Quoter可以方便地找出如何使用Roslyn生成語法。

在你的具體的例子,你重寫的VisitPropertyDeclaration方法應該是這個樣子:

using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; 
... 

    protected override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node) 
{ 
    var typeSyntax = node.Type; 

    if (node.Identifier.ValueText == "Id") 
    { 
     typeSyntax = SyntaxFactory.IdentifierName("string"); 
    } 

    var newProperty = PropertyDeclaration(
       PredefinedType(
        Token(SyntaxKind.LongKeyword)), 
       Identifier("Id")) 
      .WithModifiers(
       TokenList(
        Token(SyntaxKind.PublicKeyword))) 
      .WithAccessorList(
       AccessorList(
        List(new AccessorDeclarationSyntax[]{ 
         AccessorDeclaration(
          SyntaxKind.GetAccessorDeclaration) 
         .WithSemicolonToken(
          Token(SyntaxKind.SemicolonToken)), 
         AccessorDeclaration(
          SyntaxKind.SetAccessorDeclaration) 
         .WithSemicolonToken(
          Token(SyntaxKind.SemicolonToken))}))) 
      .NormalizeWhitespace(); 

    return newProperty; 
}  
+0

我注意到了,但我無法弄清楚如何初始化它,因此問題。 – bloudraak 2012-02-09 04:37:12

+0

查看更新的答案。 – 2012-02-09 07:05:30

+0

正是我在找的。謝謝。 – bloudraak 2012-02-10 03:31:17