SyntaxFactory 高级用法 - Part 2
本文档介绍 SyntaxFactory 的高级用法和技巧(第二部分)。
文档信息
- 难度级别: 高级
- 预计阅读时间: 20 分钟
---
## 鐢熸垚鏋氫妇
```csharp
/// <summary>
/// 鐢熸垚鏋氫妇鐨勭ず渚?
/// </summary>
public class EnumGeneration
{
/// <summary>
/// 鐢熸垚绠€鍗曟灇涓?
/// public enum Status
/// {
/// Active,
/// Inactive,
/// Pending
/// }
/// </summary>
public EnumDeclarationSyntax GenerateSimpleEnum()
{
return EnumDeclaration("Status")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddMembers(
EnumMemberDeclaration("Active"),
EnumMemberDeclaration("Inactive"),
EnumMemberDeclaration("Pending"));
}
/// <summary>
/// 鐢熸垚甯﹀€肩殑鏋氫妇
/// public enum ErrorCode
/// {
/// Success = 0,
/// NotFound = 404,
/// ServerError = 500
/// }
/// </summary>
public EnumDeclarationSyntax GenerateEnumWithValues()
{
return EnumDeclaration("ErrorCode")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddMembers(
EnumMemberDeclaration("Success")
.WithEqualsValue(
EqualsValueClause(
LiteralExpression(
SyntaxKind.NumericLiteralExpression,
Literal(0)))),
EnumMemberDeclaration("NotFound")
.WithEqualsValue(
EqualsValueClause(
LiteralExpression(
SyntaxKind.NumericLiteralExpression,
Literal(404)))),
EnumMemberDeclaration("ServerError")
.WithEqualsValue(
EqualsValueClause(
LiteralExpression(
SyntaxKind.NumericLiteralExpression,
Literal(500)))));
}
}鐪熷疄浣跨敤鍦烘櫙
鍦烘櫙 1: DTO 绫荤敓鎴愬櫒
涓烘暟鎹簱琛ㄨ嚜鍔ㄧ敓鎴?DTO锛圖ata Transfer Object锛夌被銆?
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using System.Collections.Generic;
/// <summary>
/// 鍦烘櫙锛欴TO 绫荤敓鎴愬櫒
/// 鏍规嵁鏁版嵁搴撹〃缁撴瀯鑷姩鐢熸垚 DTO 绫?
/// </summary>
public class DtoGenerator
{
/// <summary>
/// 琛ㄥ垪淇℃伅
/// </summary>
public class ColumnInfo
{
public string Name { get; set; }
public string Type { get; set; }
public bool IsNullable { get; set; }
public string Description { get; set; }
}
/// <summary>
/// 鐢熸垚 DTO 绫?
/// </summary>
public CompilationUnitSyntax GenerateDto(
string tableName,
List<ColumnInfo> columns)
{
// 绫诲悕锛歎serDto
var className = $"{tableName}Dto";
// 鍒涘缓绫?
var classDecl = ClassDeclaration(className)
.AddModifiers(Token(SyntaxKind.PublicKeyword));
// 娣诲姞 XML 鏂囨。娉ㄩ噴
classDecl = classDecl.WithLeadingTrivia(
TriviaList(
Comment("/// <summary>"),
CarriageReturnLineFeed,
Comment($"/// {tableName} 琛ㄧ殑 DTO 绫?),
CarriageReturnLineFeed,
Comment("/// </summary>"),
CarriageReturnLineFeed));
// 涓烘瘡涓垪鐢熸垚灞炴€?
foreach (var column in columns)
{
var property = GenerateProperty(column);
classDecl = classDecl.AddMembers(property);
}
// 鍒涘缓鍛藉悕绌洪棿
var namespaceDecl = NamespaceDeclaration(ParseName("MyApp.Dtos"))
.AddMembers(classDecl);
// 鍒涘缓缂栬瘧鍗曞厓
return CompilationUnit()
.AddUsings(UsingDirective(ParseName("System")))
.AddMembers(namespaceDecl)
.NormalizeWhitespace();
}
/// <summary>
/// 鐢熸垚灞炴€?
/// </summary>
private PropertyDeclarationSyntax GenerateProperty(ColumnInfo column)
{
// 纭畾灞炴€х被鍨?
var typeName = column.Type;
if (column.IsNullable && IsValueType(column.Type))
{
typeName = $"{column.Type}?";
}
// 鍒涘缓灞炴€?
var property = PropertyDeclaration(
ParseTypeName(typeName),
Identifier(column.Name))
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
// 娣诲姞 XML 鏂囨。娉ㄩ噴
if (!string.IsNullOrEmpty(column.Description))
{
property = property.WithLeadingTrivia(
TriviaList(
CarriageReturnLineFeed,
Whitespace(" "),
Comment("/// <summary>"),
CarriageReturnLineFeed,
Whitespace(" "),
Comment($"/// {column.Description}"),
CarriageReturnLineFeed,
Whitespace(" "),
Comment("/// </summary>"),
CarriageReturnLineFeed,
Whitespace(" ")));
}
return property;
}
/// <summary>
/// 鍒ゆ柇鏄惁涓哄€肩被鍨?
/// </summary>
private bool IsValueType(string typeName)
{
return typeName switch
{
"int" or "long" or "short" or "byte" or
"decimal" or "double" or "float" or
"bool" or "DateTime" or "Guid" => true,
_ => false
};
}
}鍦烘櫙 2: Builder 妯″紡鐢熸垚鍣?
涓虹被鑷姩鐢熸垚 Builder 妯″紡浠g爜銆?
/// <summary>
/// 鍦烘櫙锛欱uilder 妯″紡鐢熸垚鍣?
/// 涓虹幇鏈夌被鐢熸垚娴佸紡 Builder 绫?
/// </summary>
public class BuilderPatternGenerator
{
/// <summary>
/// 涓虹被鐢熸垚 Builder
/// </summary>
public ClassDeclarationSyntax GenerateBuilder(
string targetClassName,
List<PropertyInfo> properties)
{
var builderClassName = $"{targetClassName}Builder";
// 鍒涘缓 Builder 绫?
var builderClass = ClassDeclaration(builderClassName)
.AddModifiers(Token(SyntaxKind.PublicKeyword));
// 娣诲姞绉佹湁瀛楁
foreach (var prop in properties)
{
var field = FieldDeclaration(
VariableDeclaration(ParseTypeName(prop.Type))
.AddVariables(
VariableDeclarator(Identifier($"_{ToCamelCase(prop.Name)}"))))
.AddModifiers(Token(SyntaxKind.PrivateKeyword));
builderClass = builderClass.AddMembers(field);
}
// 娣诲姞 With 鏂规硶
foreach (var prop in properties)
{
var withMethod = GenerateWithMethod(builderClassName, prop);
builderClass = builderClass.AddMembers(withMethod);
}
// 娣诲姞 Build 鏂规硶
var buildMethod = GenerateBuildMethod(targetClassName, properties);
builderClass = builderClass.AddMembers(buildMethod);
return builderClass;
}
/// <summary>
/// 鐢熸垚 With 鏂规硶
/// public PersonBuilder WithName(string name)
/// {
/// _name = name;
/// return this;
/// }
/// </summary>
private MethodDeclarationSyntax GenerateWithMethod(
string builderClassName,
PropertyInfo property)
{
var fieldName = $"_{ToCamelCase(property.Name)}";
var paramName = ToCamelCase(property.Name);
return MethodDeclaration(
IdentifierName(builderClassName),
$"With{property.Name}")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddParameterListParameters(
Parameter(Identifier(paramName))
.WithType(ParseTypeName(property.Type)))
.WithBody(Block(
// _name = name;
ExpressionStatement(
AssignmentExpression(
SyntaxKind.SimpleAssignmentExpression,
IdentifierName(fieldName),
IdentifierName(paramName))),
// return this;
ReturnStatement(ThisExpression())));
}
/// <summary>
/// 鐢熸垚 Build 鏂规硶
/// public Person Build()
/// {
/// return new Person
/// {
/// Name = _name,
/// Age = _age
/// };
/// }
/// </summary>
private MethodDeclarationSyntax GenerateBuildMethod(
string targetClassName,
List<PropertyInfo> properties)
{
// 鍒涘缓瀵硅薄鍒濆鍖栧櫒
var initializers = properties.Select(prop =>
AssignmentExpression(
SyntaxKind.SimpleAssignmentExpression,
IdentifierName(prop.Name),
IdentifierName($"_{ToCamelCase(prop.Name)}")));
return MethodDeclaration(
IdentifierName(targetClassName),
"Build")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.WithBody(Block(
ReturnStatement(
ObjectCreationExpression(IdentifierName(targetClassName))
.WithInitializer(
InitializerExpression(
SyntaxKind.ObjectInitializerExpression,
SeparatedList<ExpressionSyntax>(initializers))))));
}
private string ToCamelCase(string name)
{
if (string.IsNullOrEmpty(name)) return name;
return char.ToLower(name[0]) + name.Substring(1);
}
public class PropertyInfo
{
public string Name { get; set; }
public string Type { get; set; }
}
}鍦烘櫙 3: API 瀹㈡埛绔敓鎴愬櫒
鏍规嵁 API 瀹氫箟鑷姩鐢熸垚瀹㈡埛绔唬鐮併€?
/// <summary>
/// 鍦烘櫙锛欰PI 瀹㈡埛绔敓鎴愬櫒
/// 鏍规嵁 API 瀹氫箟鐢熸垚 HTTP 瀹㈡埛绔唬鐮?
/// </summary>
public class ApiClientGenerator
{
public class ApiEndpoint
{
public string Name { get; set; }
public string Method { get; set; } // GET, POST, PUT, DELETE
public string Path { get; set; }
public List<Parameter> Parameters { get; set; }
public string ReturnType { get; set; }
}
public class Parameter
{
public string Name { get; set; }
public string Type { get; set; }
public bool IsRequired { get; set; }
}
/// <summary>
/// 鐢熸垚 API 瀹㈡埛绔被
/// </summary>
public CompilationUnitSyntax GenerateApiClient(
string clientName,
List<ApiEndpoint> endpoints)
{
// 鍒涘缓瀹㈡埛绔被
var clientClass = ClassDeclaration(clientName)
.AddModifiers(Token(SyntaxKind.PublicKeyword));
// 娣诲姞 HttpClient 瀛楁
var httpClientField = FieldDeclaration(
VariableDeclaration(IdentifierName("HttpClient"))
.AddVariables(VariableDeclarator("_httpClient")))
.AddModifiers(
Token(SyntaxKind.PrivateKeyword),
Token(SyntaxKind.ReadOnlyKeyword));
clientClass = clientClass.AddMembers(httpClientField);
// 娣诲姞鏋勯€犲嚱鏁?
var constructor = ConstructorDeclaration(clientName)
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddParameterListParameters(
Parameter(Identifier("httpClient"))
.WithType(IdentifierName("HttpClient")))
.WithBody(Block(
ExpressionStatement(
AssignmentExpression(
SyntaxKind.SimpleAssignmentExpression,
IdentifierName("_httpClient"),
IdentifierName("httpClient")))));
clientClass = clientClass.AddMembers(constructor);
// 涓烘瘡涓鐐圭敓鎴愭柟娉?
foreach (var endpoint in endpoints)
{
var method = GenerateEndpointMethod(endpoint);
clientClass = clientClass.AddMembers(method);
}
// 鍒涘缓鍛藉悕绌洪棿
var namespaceDecl = NamespaceDeclaration(ParseName("MyApp.ApiClients"))
.AddMembers(clientClass);
// 鍒涘缓缂栬瘧鍗曞厓
return CompilationUnit()
.AddUsings(
UsingDirective(ParseName("System")),
UsingDirective(ParseName("System.Net.Http")),
UsingDirective(ParseName("System.Threading.Tasks")))
.AddMembers(namespaceDecl)
.NormalizeWhitespace();
}
/// <summary>
/// 鐢熸垚绔偣鏂规硶
/// public async Task<User> GetUserAsync(int id)
/// {
/// var response = await _httpClient.GetAsync($"/api/users/{id}");
/// response.EnsureSuccessStatusCode();
/// return await response.Content.ReadAsAsync<User>();
/// }
/// </summary>
private MethodDeclarationSyntax GenerateEndpointMethod(ApiEndpoint endpoint)
{
// 鏂规硶鍚?
var methodName = $"{endpoint.Name}Async";
// 杩斿洖绫诲瀷锛歍ask<ReturnType>
var returnType = GenericName("Task")
.AddTypeArgumentListArguments(
IdentifierName(endpoint.ReturnType));
// 鍒涘缓鏂规硶
var method = MethodDeclaration(returnType, methodName)
.AddModifiers(
Token(SyntaxKind.PublicKeyword),
Token(SyntaxKind.AsyncKeyword));
// 娣诲姞鍙傛暟
foreach (var param in endpoint.Parameters)
{
method = method.AddParameterListParameters(
Parameter(Identifier(param.Name))
.WithType(ParseTypeName(param.Type)));
}
// 鐢熸垚鏂规硶浣擄紙绠€鍖栫増锛?
var methodBody = GenerateMethodBody(endpoint);
method = method.WithBody(Block(methodBody));
return method;
}
private StatementSyntax[] GenerateMethodBody(ApiEndpoint endpoint)
{
// 绠€鍖栫殑鏂规硶浣撶敓鎴?
// 瀹為檯搴旇鏍规嵁 HTTP 鏂规硶鐢熸垚涓嶅悓鐨勪唬鐮?
return new[]
{
// var response = await _httpClient.GetAsync(...);
LocalDeclarationStatement(
VariableDeclaration(IdentifierName("var"))
.AddVariables(
VariableDeclarator("response")
.WithInitializer(
EqualsValueClause(
AwaitExpression(
InvocationExpression(
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
IdentifierName("_httpClient"),
IdentifierName($"{endpoint.Method}Async")))))))),
// return default;
ReturnStatement(
LiteralExpression(SyntaxKind.DefaultLiteralExpression))
};
}
}瀛楃涓叉彃鍊?vs SyntaxFactory
浼樼己鐐瑰姣?
瀛楃涓叉彃鍊兼柟寮?
浼樼偣锛?
- 鉁?绠€鍗曠洿瑙傦紝鏄撲簬鐞嗚В
- 鉁?蹇€熷師鍨嬪紑鍙?
- 鉁?閫傚悎绠€鍗曠殑浠g爜鐢熸垚
缂虹偣锛?
- 鉂?闅句互缁存姢澶嶆潅鐨勪唬鐮佺粨鏋?
- 鉂?缂哄皯璇硶楠岃瘉
- 鉂?鏍煎紡鍖栧洶闅?
- 鉂?闅句互澶勭悊鐗规畩瀛楃鍜岃浆涔?
// 瀛楃涓叉彃鍊肩ず渚?
public string GenerateClassUsingString(string className)
{
return $@"
public class {className}
{{
public string Name {{ get; set; }}
public int Age {{ get; set; }}
}}";
}SyntaxFactory 鏂瑰紡
浼樼偣锛?
- 鉁?绫诲瀷瀹夊叏锛岀紪璇戞椂妫€鏌?
- 鉁?鏄撲簬缁存姢鍜岄噸鏋?
- 鉁?鑷姩鏍煎紡鍖?
- 鉁?鏀寔澶嶆潅鐨勪唬鐮佺粨鏋?
- 鉁?鍙互鍒╃敤 Roslyn 鐨勮娉曞垎鏋?
缂虹偣锛?
- 鉂?瀛︿範鏇茬嚎闄″抄
- 鉂?浠g爜鍐楅暱
- 鉂?鍒濇湡寮€鍙戦€熷害杈冩參
// SyntaxFactory 绀轰緥
public ClassDeclarationSyntax GenerateClassUsingSyntaxFactory(
string className)
{
return ClassDeclaration(className)
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddMembers(
PropertyDeclaration(
PredefinedType(Token(SyntaxKind.StringKeyword)),
"Name")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken))));
}浣跨敤鍦烘櫙寤鸿
浣跨敤瀛楃涓叉彃鍊肩殑鍦烘櫙
- 绠€鍗曠殑浠g爜鐗囨鐢熸垚
- 蹇€熷師鍨嬪紑鍙?
- 涓€娆℃€х殑浠g爜鐢熸垚浠诲姟
- 妯℃澘闈炲父绠€鍗曚笖涓嶄細鏀瑰彉
// 鉁?閫傚悎瀛楃涓叉彃鍊硷細绠€鍗曠殑灞炴€х敓鎴?
public string GenerateSimpleProperty(string name, string type)
{
return $"public {type} {name} {{ get; set; }}";
}浣跨敤 SyntaxFactory 鐨勫満鏅?
- 澶嶆潅鐨勪唬鐮佺粨鏋?
- 闇€瑕佺淮鎶ょ殑鐢熸垚鍣?
- 闇€瑕佽娉曢獙璇?
- 闇€瑕佷笌鐜版湁浠g爜闆嗘垚
// 鉁?閫傚悎 SyntaxFactory锛氬鏉傜殑绫荤敓鎴?
public ClassDeclarationSyntax GenerateComplexClass(
string className,
List<PropertyInfo> properties)
{
var classDecl = ClassDeclaration(className)
.AddModifiers(Token(SyntaxKind.PublicKeyword));
foreach (var prop in properties)
{
var property = GenerateProperty(prop);
classDecl = classDecl.AddMembers(property);
}
return classDecl;
}娣峰悎浣跨敤绛栫暐
鍦ㄥ疄闄呴」鐩腑锛屽彲浠ョ粨鍚堜袱绉嶆柟寮忕殑浼樼偣锛?
/// <summary>
/// 娣峰悎浣跨敤瀛楃涓插拰 SyntaxFactory
/// </summary>
public class HybridCodeGeneration
{
/// <summary>
/// 浣跨敤瀛楃涓茬敓鎴愮畝鍗曢儴鍒嗭紝SyntaxFactory 鐢熸垚澶嶆潅閮ㄥ垎
/// </summary>
public CompilationUnitSyntax GenerateCode(string className)
{
// 浣跨敤 SyntaxFactory 鐢熸垚涓昏缁撴瀯
var classDecl = ClassDeclaration(className)
.AddModifiers(Token(SyntaxKind.PublicKeyword));
// 瀵逛簬绠€鍗曠殑鏂规硶浣擄紝鍙互浣跨敤 ParseStatement
var methodBody = ParseStatement(@"
Console.WriteLine(""Hello, World!"");
return 42;
");
var method = MethodDeclaration(
PredefinedType(Token(SyntaxKind.IntKeyword)),
"GetValue")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.WithBody(Block(methodBody));
classDecl = classDecl.AddMembers(method);
return CompilationUnit()
.AddMembers(classDecl)
.NormalizeWhitespace();
}
}甯歌闂瑙g瓟锛團AQ锛?
Q1: 濡備綍鐢熸垚甯﹀懡鍚嶇┖闂寸殑瀹屾暣浠g爜鏂囦欢锛?
A: 浣跨敤 CompilationUnit 鍜?NamespaceDeclaration锛?
var compilationUnit = CompilationUnit()
.AddUsings(
UsingDirective(ParseName("System")))
.AddMembers(
NamespaceDeclaration(ParseName("MyNamespace"))
.AddMembers(
ClassDeclaration("MyClass")
.AddModifiers(Token(SyntaxKind.PublicKeyword))))
.NormalizeWhitespace();
string code = compilationUnit.ToFullString();Q2: 濡備綍涓虹敓鎴愮殑浠g爜娣诲姞 XML 鏂囨。娉ㄩ噴锛?
A: 浣跨敤 WithLeadingTrivia 娣诲姞娉ㄩ噴锛?
var classDecl = ClassDeclaration("MyClass")
.WithLeadingTrivia(
TriviaList(
Comment("/// <summary>"),
CarriageReturnLineFeed,
Comment("/// 鎴戠殑绫?),
CarriageReturnLineFeed,
Comment("/// </summary>"),
CarriageReturnLineFeed));Q3: 濡備綍鐢熸垚琛ㄨ揪寮忎富浣撴垚鍛橈紙Expression-bodied members锛夛紵
A: 浣跨敤 WithExpressionBody 鍜?ArrowExpressionClause锛?
// 鐢熸垚锛歱ublic int GetValue() => 42;
var method = MethodDeclaration(
PredefinedType(Token(SyntaxKind.IntKeyword)),
"GetValue")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.WithExpressionBody(
ArrowExpressionClause(
LiteralExpression(
SyntaxKind.NumericLiteralExpression,
Literal(42))))
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));Q4: 濡備綍鐢熸垚 async/await 浠g爜锛?
A: 浣跨敤 AsyncKeyword 淇グ绗﹀拰 AwaitExpression锛?
// 鐢熸垚锛歱ublic async Task<int> GetValueAsync()
var method = MethodDeclaration(
GenericName("Task")
.AddTypeArgumentListArguments(
PredefinedType(Token(SyntaxKind.IntKeyword))),
"GetValueAsync")
.AddModifiers(
Token(SyntaxKind.PublicKeyword),
Token(SyntaxKind.AsyncKeyword))
.WithBody(Block(
ReturnStatement(
AwaitExpression(
InvocationExpression(
IdentifierName("SomeAsyncMethod"))))));Q5: 濡備綍鐢熸垚 Lambda 琛ㄨ揪寮忥紵
A: 浣跨敤 SimpleLambdaExpression 鎴?ParenthesizedLambdaExpression锛?
// 鐢熸垚锛歺 => x * 2
var lambda = SimpleLambdaExpression(
Parameter(Identifier("x")),
BinaryExpression(
SyntaxKind.MultiplyExpression,
IdentifierName("x"),
LiteralExpression(
SyntaxKind.NumericLiteralExpression,
Literal(2))));
// 鐢熸垚锛?x, y) => x + y
var multiParamLambda = ParenthesizedLambdaExpression(
ParameterList(
SeparatedList(new[]
{
Parameter(Identifier("x")),
Parameter(Identifier("y"))
})),
BinaryExpression(
SyntaxKind.AddExpression,
IdentifierName("x"),
IdentifierName("y")));Q6: 濡備綍鐢熸垚 LINQ 鏌ヨ琛ㄨ揪寮忥紵
A: 浣跨敤 QueryExpression 鍜岀浉鍏崇殑鏌ヨ瀛愬彞锛?
// 鐢熸垚锛歠rom x in numbers where x > 5 select x * 2
var query = QueryExpression(
QueryBody(
SingletonList<QueryClauseSyntax>(
WhereClause(
BinaryExpression(
SyntaxKind.GreaterThanExpression,
IdentifierName("x"),
LiteralExpression(
SyntaxKind.NumericLiteralExpression,
Literal(5))))),
SelectClause(
BinaryExpression(
SyntaxKind.MultiplyExpression,
IdentifierName("x"),
LiteralExpression(
SyntaxKind.NumericLiteralExpression,
Literal(2)))),
null))
.WithFromClause(
FromClause(
Identifier("x"),
IdentifierName("numbers")));Q7: 濡備綍鐢熸垚 switch 琛ㄨ揪寮忥紙C# 8.0+锛夛紵
A: 浣跨敤 SwitchExpression锛?
// 鐢熸垚锛歷alue switch { 1 => "one", 2 => "two", _ => "other" }
var switchExpr = SwitchExpression(
IdentifierName("value"),
SeparatedList(new[]
{
SwitchExpressionArm(
ConstantPattern(
LiteralExpression(
SyntaxKind.NumericLiteralExpression,
Literal(1))),
LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal("one"))),
SwitchExpressionArm(
ConstantPattern(
LiteralExpression(
SyntaxKind.NumericLiteralExpression,
Literal(2))),
LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal("two"))),
SwitchExpressionArm(
DiscardPattern(),
LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal("other")))
}));Q8: 濡備綍鐢熸垚 record 绫诲瀷锛圕# 9.0+锛夛紵
A: 浣跨敤 RecordDeclaration锛?
// 鐢熸垚锛歱ublic record Person(string Name, int Age);
var record = RecordDeclaration(
Token(SyntaxKind.RecordKeyword),
"Person")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.WithParameterList(
ParameterList(
SeparatedList(new[]
{
Parameter(Identifier("Name"))
.WithType(PredefinedType(Token(SyntaxKind.StringKeyword))),
Parameter(Identifier("Age"))
.WithType(PredefinedType(Token(SyntaxKind.IntKeyword)))
})))
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));Q9: 濡備綍鐢熸垚 using 澹版槑锛圕# 8.0+锛夛紵
A: 浣跨敤 LocalDeclarationStatement 鍜?UsingKeyword锛?
// 鐢熸垚锛歶sing var stream = File.OpenRead("file.txt");
var usingDecl = LocalDeclarationStatement(
VariableDeclaration(IdentifierName("var"))
.AddVariables(
VariableDeclarator("stream")
.WithInitializer(
EqualsValueClause(
InvocationExpression(
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
IdentifierName("File"),
IdentifierName("OpenRead")))
.AddArgumentListArguments(
Argument(
LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal("file.txt"))))))))
.AddModifiers(Token(SyntaxKind.UsingKeyword));Q10: 濡備綍鐢熸垚 nullable 寮曠敤绫诲瀷娉ㄨВ锛?
A: 浣跨敤 NullableType锛?
// 鐢熸垚锛歴tring? name
var nullableType = NullableType(
PredefinedType(Token(SyntaxKind.StringKeyword)));
// 鍦ㄥ睘鎬т腑浣跨敤
var property = PropertyDeclaration(
nullableType,
"Name")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));Q11: 濡備綍鐢熸垚 init 璁块棶鍣紙C# 9.0+锛夛紵
A: 浣跨敤 InitAccessorDeclaration锛?
// 鐢熸垚锛歱ublic string Name { get; init; }
var property = PropertyDeclaration(
PredefinedType(Token(SyntaxKind.StringKeyword)),
"Name")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.InitAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));Q12: 濡備綍鐢熸垚 pattern matching锛?
A: 浣跨敤鍚勭 Pattern 绫诲瀷锛?
// 鐢熸垚锛歩f (obj is string s) { }
var isPattern = IsPatternExpression(
IdentifierName("obj"),
DeclarationPattern(
PredefinedType(Token(SyntaxKind.StringKeyword)),
SingleVariableDesignation(Identifier("s"))));
var ifStatement = IfStatement(
isPattern,
Block());Q13: 濡備綍鐢熸垚 tuple 绫诲瀷锛?
A: 浣跨敤 TupleType锛?
// 鐢熸垚锛?int, string)
var tupleType = TupleType(
SeparatedList(new[]
{
TupleElement(PredefinedType(Token(SyntaxKind.IntKeyword))),
TupleElement(PredefinedType(Token(SyntaxKind.StringKeyword)))
}));
// 鐢熸垚甯﹀悕绉扮殑 tuple锛?int id, string name)
var namedTupleType = TupleType(
SeparatedList(new[]
{
TupleElement(
PredefinedType(Token(SyntaxKind.IntKeyword)),
Identifier("id")),
TupleElement(
PredefinedType(Token(SyntaxKind.StringKeyword)),
Identifier("name"))
}));Q14: 濡備綍鐢熸垚 local function锛?
A: 浣跨敤 LocalFunctionStatement锛?
// 鐢熸垚锛歩nt Add(int a, int b) => a + b;
var localFunction = LocalFunctionStatement(
PredefinedType(Token(SyntaxKind.IntKeyword)),
"Add")
.AddParameterListParameters(
Parameter(Identifier("a"))
.WithType(PredefinedType(Token(SyntaxKind.IntKeyword))),
Parameter(Identifier("b"))
.WithType(PredefinedType(Token(SyntaxKind.IntKeyword))))
.WithExpressionBody(
ArrowExpressionClause(
BinaryExpression(
SyntaxKind.AddExpression,
IdentifierName("a"),
IdentifierName("b"))))
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));Q15: 濡備綍澶勭悊鐢熸垚浠g爜涓殑鐗规畩瀛楃鍜岃浆涔夛紵
A: Roslyn 浼氳嚜鍔ㄥ鐞嗚浆涔夛紝浣嗕綘涔熷彲浠ヤ娇鐢?verbatim 瀛楃涓诧細
// 鏅€氬瓧绗︿覆锛堣嚜鍔ㄨ浆涔夛級
var normalString = LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal("C:\\Path\\To\\File"));
// Verbatim 瀛楃涓?
var verbatimString = LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal(@"C:\Path\To\File", @"C:\Path\To\File"));馃挕 鏈€浣冲疄璺?
瀹炶返 1: 浣跨敤杈呭姪鏂规硶灏佽甯歌妯″紡
// 鉁?濂界殑鍋氭硶锛氬皝瑁呭父瑙佹ā寮?
public class CodeGenerationHelpers
{
/// <summary>
/// 鍒涘缓鍏叡鑷姩灞炴€?
/// </summary>
public static PropertyDeclarationSyntax CreateAutoProperty(
string typeName,
string propertyName)
{
return PropertyDeclaration(
ParseTypeName(typeName),
Identifier(propertyName))
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
}
/// <summary>
/// 浣跨敤杈呭姪鏂规硶
/// </summary>
public ClassDeclarationSyntax GenerateClass()
{
return ClassDeclaration("Person")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddMembers(
CreateAutoProperty("string", "Name"),
CreateAutoProperty("int", "Age"));
}
}鍘熷洜锛氭彁楂樹唬鐮佸鐢ㄦ€у拰鍙淮鎶ゆ€с€?
瀹炶返 2: 浣跨敤鏋勫缓鍣ㄦā寮忕粍缁囧鏉傜敓鎴愰€昏緫
// 鉁?濂界殑鍋氭硶锛氫娇鐢ㄦ瀯寤哄櫒妯″紡
public class ClassBuilder
{
private string _className;
private List<PropertyDeclarationSyntax> _properties = new();
public ClassBuilder WithName(string name)
{
_className = name;
return this;
}
public ClassBuilder AddProperty(string type, string name)
{
var property = PropertyDeclaration(
ParseTypeName(type),
Identifier(name))
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
_properties.Add(property);
return this;
}
public ClassDeclarationSyntax Build()
{
return ClassDeclaration(_className)
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddMembers(_properties.ToArray());
}
}鍘熷洜锛氫娇澶嶆潅鐨勪唬鐮佺敓鎴愰€昏緫鏇存竻鏅般€佹洿鏄撶淮鎶ゃ€?
瀹炶返 3: 濮嬬粓鏍煎紡鍖栫敓鎴愮殑浠g爜
// 鉁?濂界殑鍋氭硶锛氭牸寮忓寲浠g爜
public string GenerateClass(string className)
{
var classDecl = ClassDeclaration(className)
.AddModifiers(Token(SyntaxKind.PublicKeyword));
// 鏍煎紡鍖栦唬鐮?
var formatted = classDecl.NormalizeWhitespace();
return formatted.ToFullString();
}鍘熷洜锛氱‘淇濈敓鎴愮殑浠g爜鍏锋湁涓€鑷寸殑鏍煎紡鍜岃壇濂界殑鍙鎬с€?
鈿狅笍 甯歌閿欒
閿欒 1: 蹇樿娣诲姞鍒嗗彿鏍囪
闂: 鏌愪簺璇硶鑺傜偣闇€瑕佹樉寮忔坊鍔犲垎鍙锋爣璁般€?
// 鉂?閿欒锛氱己灏戝垎鍙锋爣璁?
var accessor = AccessorDeclaration(SyntaxKind.GetAccessorDeclaration);
// 缁撴灉锛歡et // 缂哄皯鍒嗗彿瑙e喅鏂规:
// 鉁?姝g‘锛氭坊鍔犲垎鍙锋爣璁?
var accessor = AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
// 缁撴灉锛歡et;閿欒 2: 娉涘瀷绾︽潫椤哄簭閿欒
闂: 娉涘瀷绾︽潫蹇呴』鎸夌壒瀹氶『搴忔坊鍔犮€?
// 鉂?閿欒锛氱害鏉熼『搴忛敊璇?
var classDecl = ClassDeclaration("MyClass")
.AddTypeParameterListParameters(TypeParameter("T"))
.AddConstraintClauses(
TypeParameterConstraintClause("T")
.AddConstraints(
ConstructorConstraint(), // new() 蹇呴』鍦ㄦ渶鍚?
ClassOrStructConstraint(SyntaxKind.ClassConstraint)));瑙e喅鏂规:
// 鉁?姝g‘锛氱害鏉熼『搴忔纭?
var classDecl = ClassDeclaration("MyClass")
.AddTypeParameterListParameters(TypeParameter("T"))
.AddConstraintClauses(
TypeParameterConstraintClause("T")
.AddConstraints(
ClassOrStructConstraint(SyntaxKind.ClassConstraint),
ConstructorConstraint())); // new() 鍦ㄦ渶鍚?閿欒 3: 蹇樿娣诲姞 using 鎸囦护
闂: 鐢熸垚鐨勪唬鐮佷娇鐢ㄤ簡绫诲瀷浣嗘病鏈夋坊鍔犵浉搴旂殑 using 鎸囦护銆?
// 鉂?閿欒锛氱己灏?using 鎸囦护
var compilationUnit = CompilationUnit()
.AddMembers(
NamespaceDeclaration(ParseName("MyNamespace"))
.AddMembers(classDecl));
// 鐢熸垚鐨勪唬鐮佸彲鑳芥棤娉曠紪璇戯紝鍥犱负缂哄皯蹇呰鐨?using瑙e喅鏂规:
// 鉁?姝g‘锛氭坊鍔犲繀瑕佺殑 using 鎸囦护
var compilationUnit = CompilationUnit()
.AddUsings(
UsingDirective(ParseName("System")),
UsingDirective(ParseName("System.Collections.Generic")))
.AddMembers(
NamespaceDeclaration(ParseName("MyNamespace"))
.AddMembers(classDecl));馃敆 鐩稿叧鏂囨。
- 杩斿洖绱㈠紩
- SyntaxFactory 鍩虹 - 瀛︿範 SyntaxFactory 鐨勫熀鏈娇鐢?
- 浠g爜鏋勫缓妯″紡 - 瀛︿範甯哥敤鐨勪唬鐮佹瀯寤烘ā寮?
- 鏍煎紡鍖栧拰缇庡寲 - 瀛︿範濡備綍鏍煎紡鍖栫敓鎴愮殑浠g爜
- [鏈€浣冲疄璺礭(./best-practices.md) - 鎺屾彙浠g爜鐢熸垚鐨勬渶浣冲疄璺?
鍏朵粬鐩稿叧鏂囨。
- 璇硶鏍戝熀纭€ - 浜嗚В璇硶鏍戠殑鍩烘湰姒傚康
- 璇箟妯″瀷 API - 绗﹀彿鍜岀被鍨嬬郴缁?
- 缂栬瘧 API - 缂栬瘧鍜屽厓鏁版嵁寮曠敤
馃摎 涓嬩竴姝?
瀛︿範瀹屾湰鏂囨。鍚庯紝寤鸿缁х画瀛︿範锛?
- 浠g爜鏋勫缓妯″紡 - 瀛︿範濡備綍缁勭粐澶嶆潅鐨勪唬鐮佺敓鎴愰€昏緫
- [鏈€浣冲疄璺礭(./best-practices.md) - 鎺屾彙浠g爜鐢熸垚鐨勬渶浣冲疄璺靛拰鎬ц兘浼樺寲
- 瀹炴垬绀轰緥 - 鏌ョ湅瀹屾暣鐨勬簮鐢熸垚鍣ㄧず渚?
**鏈€鍚庢洿鏂?*: 2026-02-05
鏂囨。鐗堟湰: 1.0
📝 相关文档
最后更新: 2025-01-21