2012-02-09 47 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