使用Roslyn将自定义属性添加到C#类 [英] Adding custom attributes to C# classes using Roslyn
问题描述
使用系统将以下类考虑在文件 MyClass.cs中
Consider the following class in a file "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;
}
/* ... */
}
当前,我手动创建数据合同类,如下所示:
Currently I manually create data contract classes looking as follows:
[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,因此它看起来就像我手动创建的类。当前我有以下内容:
I'd like to use Roslyn to rewrite "MyClass.cs" so its looks like the class I create by hand. Currently I have the following:
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,但是没有成功。一个如何添加自定义属性?
I have been trying to find a way to add the DataMember and DataContract custom attributes to MyClass but have been unsuccessful. How does one add the custom attributes?
推荐答案
Syntax.PropertyDeclaration 的参数之一code>方法是适用于该属性的属性列表。像所有
Syntax
元素一样,它是在静态 SyntaxFactory
类上使用工厂方法构造的。
One of the parameters of the Syntax.PropertyDeclaration
method is a list of attributes that apply to the attribute. Like all Syntax
elements, it is constructed using a factory method on the static SyntaxFactory
class.
Roslyn Quoter 可以很方便地弄清楚如何使用Roslyn生成语法
The Roslyn Quoter can be handy for figuring out how to generate syntax using Roslyn.
在您的特定示例中,重写器的 VisitPropertyDeclaration
方法应类似于:
In your particular example, the VisitPropertyDeclaration
method of your rewriter should look something like:
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;
}
这篇关于使用Roslyn将自定义属性添加到C#类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!