[英]How do I get autoproperties on one line when generating code with Roslyn?
I have the following partial code which I use to generate datacontracts based on an excel-file we use for customer facing workshops and such.我有以下部分代码,用于根据我们用于面向客户的研讨会等的 excel 文件生成数据合同。
private PropertyDeclarationSyntax[] GenerateProperties()
{
var props = new List<PropertyDeclarationSyntax>();
props.Add(SF.PropertyDeclaration(SF.ParseTypeName("IMigrationInformation"), "MigrationInformation")
.AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.OverrideKeyword))
.AddAccessorListAccessors(
SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithBody(SF.Block(SF.ReturnStatement(SF.ObjectCreationExpression(SF.ParseTypeName($"{Form.RegistryName}MigrationInformation")))))
));
foreach (var field in Form.AllDataFields().Where(f => f.FieldTypeInfo != null))
{
props.Add(SF.PropertyDeclaration(SF.ParseTypeName(field.FieldTypeInfo.BackingType.Name), field.SafeName)
.AddModifiers(SF.Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken)),
SF.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken))
));
}
return props.ToArray();
}
The code works surprisingly well with one small snag.该代码在一个小问题上运行得非常好。 The code generated looks like this:生成的代码如下所示:
public string VariableName
{
get;
set;
}
And I really want it to look like this:我真的希望它看起来像这样:
public string VariableName { get; set; }
Does anyone know how to do this, if possible?如果可能的话,有谁知道如何做到这一点?
I got the exact same problem.我遇到了完全相同的问题。 In my case, I was saving the code to file after converting it to a string something like this:就我而言,我将代码转换为类似这样的字符串后将其保存到文件中:
private void WriteCodeToFile(NamespaceDeclarationSyntax ns)
{
var codeAsString = ns.NormalizeWhitespace()
.ToFullString();
File.WriteAllText(destFileName, codeAsString);
}
So, in that case, I just solved it byrunning a regex replace on the string, in an extension method:因此,在这种情况下,我只是通过在扩展方法中对字符串运行正则表达式替换来解决它:
private static readonly Regex AutoPropRegex = new Regex(@"\s*\{\s*get;\s*set;\s*}\s");
public static string FormatAutoPropertiesOnOneLine(this string str)
{
return AutoPropRegex.Replace(str, " { get; set; }");
}
And then call it after converting it to string:然后在将其转换为字符串后调用它:
var codeAsString = ns.NormalizeWhitespace()
.ToFullString()
.FormatAutoPropertiesOnOneLine();
You are not speficying how you do your file-writing step (if any), so if this is not relevant at all in your case, I apologize for not targeting your question 100%.您没有具体说明如何执行文件编写步骤(如果有),因此如果这与您的情况完全无关,我很抱歉没有 100% 以您的问题为目标。 In any case, someone else might benefit from it.无论如何,其他人可能会从中受益。
You could implement a CSharpSyntaxRewriter and than apply it to a parent SyntaxNode:您可以实现 CSharpSyntaxRewriter 并将其应用于父 SyntaxNode:
public static class WhitespaceFormatter
{
public static SyntaxNode NormalizeWhitespacesSingleLineProperties(this SyntaxNode node) =>
node.NormalizeWhitespace().SingleLineProperties();
public static SyntaxNode SingleLineProperties(this SyntaxNode node) => new SingleLinePropertyRewriter().Visit(node);
class SingleLinePropertyRewriter : CSharpSyntaxRewriter
{
public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node) =>
node.NormalizeWhitespace(indentation: "", eol: " ")
.WithLeadingTrivia(node.GetLeadingTrivia())
.WithTrailingTrivia(node.GetTrailingTrivia());
}
}
Use NormalizeWhitespacesSingleLineProperties
to apply default whitespaces to everything but property declarations which will be written to a single line.使用NormalizeWhitespacesSingleLineProperties
将默认空格应用于除将写入一行的属性声明之外的所有内容。 Make sure not to call Format
or NormalizeWhitespace()
on your node afterwards, because it will again clutter your property declarations.确保之后不要在您的节点上调用Format
或NormalizeWhitespace()
,因为它会再次使您的属性声明变得混乱。
As one of simple solution (another way create a nodes and tokens with correct trivias) just use SyntaxNodeExtensions.NormalizeWhitespace(...)
for nodes that you want to represent at the one line:作为一种简单的解决方案(另一种方式创建节点和具有正确琐事的标记),只需将SyntaxNodeExtensions.NormalizeWhitespace(...)
用于要在一行表示的节点:
...
foreach (var field in Form.AllDataFields().Where(f => f.FieldTypeInfo != null))
{
props.Add(SF.PropertyDeclaration(SF.ParseTypeName(field.FieldTypeInfo.BackingType.Name), field.SafeName)
.AddModifiers(SF.Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken)),
SF.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken))
).NormalizeWhitespace(indentation: "", eol: " "));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.