使用Roslyn将自定义属性添加到C#类

考虑文件“MyClass.cs”中的以下类

using System; public class MyClass : Entity { 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; } } 

我想用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; } } 

我一直在尝试找到一种方法将DataMember和DataContract自定义属性添加到MyClass但是不成功。 如何添加自定义属性?

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; }