gpt4 book ai didi

c# - 使用 Roslyn 将自动实现的属性添加到类

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

我正在尝试通过从头开始构建现有但简单的应用程序来学习 Roslyn,这似乎是一种有效的学习方式。无论如何,我有以下代码:

var root = (CompilationUnitSyntax)document.GetSyntaxRoot();

// Add the namespace
var namespaceAnnotation = new SyntaxAnnotation();
root = root.WithMembers(
Syntax.NamespaceDeclaration(
Syntax.ParseName("ACO"))
.NormalizeWhitespace()
.WithAdditionalAnnotations(namespaceAnnotation));
document = document.UpdateSyntaxRoot(root);

// Add a class to the newly created namespace, and update the document
var namespaceNode = (NamespaceDeclarationSyntax)root
.GetAnnotatedNodesAndTokens(namespaceAnnotation)
.Single()
.AsNode();

var classAnnotation = new SyntaxAnnotation();
var baseTypeName = Syntax.ParseTypeName("System.Windows.Forms.Form");
SyntaxTokenList syntaxTokenList = new SyntaxTokenList()
{
Syntax.Token(SyntaxKind.PublicKeyword)
};

var newNamespaceNode = namespaceNode
.WithMembers(
Syntax.List<MemberDeclarationSyntax>(
Syntax.ClassDeclaration("MainForm")
.WithAdditionalAnnotations(classAnnotation)
.AddBaseListTypes(baseTypeName)
.WithModifiers(Syntax.Token(SyntaxKind.PublicKeyword))));

root = root.ReplaceNode(namespaceNode, newNamespaceNode).NormalizeWhitespace();
document = document.UpdateSyntaxRoot(root);


var attributes = Syntax.List(Syntax.AttributeDeclaration(Syntax.SeparatedList(Syntax.Attribute(Syntax.ParseName("STAThread")))));


// Find the class just created, add a method to it and update the document
var classNode = (ClassDeclarationSyntax)root
.GetAnnotatedNodesAndTokens(classAnnotation)
.Single()
.AsNode();

var syntaxList = Syntax.List<MemberDeclarationSyntax>(
Syntax.MethodDeclaration(
Syntax.ParseTypeName("void"), "Main")
.WithModifiers(Syntax.TokenList(Syntax.Token(SyntaxKind.PublicKeyword)))
.WithAttributes(attributes)
.WithBody(
Syntax.Block()));
syntaxList.Add(Syntax.PropertyDeclaration(Syntax.ParseTypeName("System.Windows.Forms.Timer"), "Ticker"));
var newClassNode = classNode
.WithMembers(syntaxList);

root = root.ReplaceNode(classNode, newClassNode).NormalizeWhitespace();
document = document.UpdateSyntaxRoot(root);

在 IDocument 中输出以下代码。

namespace ACO
{
public class MainForm : System.Windows.Forms.Form
{
[STAThread]
public void Main()
{
}
}
}

虽然它看起来应该更像这样(注意我试图添加 Timer 属性)

namespace ACO
{
public class MainForm : System.Windows.Forms.Form
{
public System.Windows.Forms.Timer Ticker {get; set;}

[STAThread]
public void Main()
{
}
}
}

另外,我为这样一个简单的过程编写的代码似乎过多了。除了我的主要问题之外,人们能否就如何以更优雅的方式解决这个问题提出建议?可能是博客链接、代码片段或其他内容?


事实证明我需要更改这一行:

syntaxList.Add(Syntax.PropertyDeclaration(Syntax.ParseTypeName("System.Windows.Forms.Timer"), "Ticker"));

到这一行:

syntaxList = syntaxList.Add(Syntax.PropertyDeclaration(Syntax.ParseTypeName("System.Windows.Forms.Timer"), "Ticker"));

但是,现在我得到了这个输出:

namespace ACO
{
public class MainForm : System.Windows.Forms.Form
{
[STAThread]
public void Main()
{
}

System.Windows.Forms.Timer Ticker
{
}
}
}

现在我没有得到“get;set;”属性中的文本。有谁知道我错过了什么?

最佳答案

我认为未添加该属性的原因是 SyntaxList 与 Roslyn 中的其他所有内容一样是不可变的。 Add() 不返回更新后的 SyntaxList 吗? (我现在无法验证这一点,我还没有切换到新的 CTP。)

在 Roslyn 中,这样的代码可能非常冗长,但您却让它变得比必要的更复杂。如果您自下而上构建语法树,则不必在每次更改后更新 root:首先创建类的成员,然后是类,然后是 namespace 。如果这样做,您根本不必处理所有注释。

关于c# - 使用 Roslyn 将自动实现的属性添加到类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11336712/

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