[英]Inheritance of auto-implemented property with only getter needed in a derived class
[英]Adding Auto-Implemented Property to class using Roslyn
我试图通过从头开始构建现有但简单的应用程序来学习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
{
}
}
}
现在我没有得到“得到;设定;” 财产内的文字。 有谁知道我错过了什么?
我认为没有添加属性的原因是,与Roslyn中的其他所有内容一样, SyntaxList
是不可变的。 Add()
返回更新的SyntaxList
吗? (我现在无法验证这一点,我还没有切换到新的CTP。)
在Roslyn中这样的代码可能非常冗长,但是你要使它比必要的更复杂。 如果从下到上构建语法树,则不必在每次更改后更新root
:首先创建类的成员,然后创建类,然后创建名称空间。 如果你这样做,你将不必处理所有的注释。
使用新的流畅API(.With ...()方法),您现在可以使用:
Syntax.PropertyDeclaration(Syntax.ParseTypeName("int"), "MyProperty")
.WithAccessorList(
Syntax.AccessorList(
Syntax.List(
Syntax.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Syntax.Token(SyntaxKind.SemicolonToken)),
Syntax.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Syntax.Token(SyntaxKind.SemicolonToken)))));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.