gpt4 book ai didi

c# - 使用 Roslyn 向 C# 类添加自定义属性

转载 作者:可可西里 更新时间:2023-11-01 08:25:35 25 4
gpt4 key购买 nike

考虑文件“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;
}
}

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

关于c# - 使用 Roslyn 向 C# 类添加自定义属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9204875/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com