为何Roslyn的SyntaxGenerator不生成params数组与可选参数?
问题原因
SyntaxGenerator的核心设计目标是提供跨C#/VB.NET的通用语法生成能力,现有实现中确实未对参数的params修饰符、可选参数默认值做处理,属于已知的未实现特性,而非运行错误。它默认只会生成方法签名的核心元数据部分(参数类型、名称、返回值等),不会自动读取符号上的扩展参数属性生成对应语法节点。
解决方法
可以不直接调用传入IMethodSymbol的重载,而是自行拆解符号信息,手动构造参数节点,再传入MethodDeclaration方法,无需事后修改语法树。示例代码如下:
// 先读取方法的修饰符,可自行扩展处理virtual/override/async等 private static DeclarationModifiers GetMethodModifiers(IMethodSymbol method) { var modifiers = DeclarationModifiers.None; if (method.IsStatic) modifiers |= DeclarationModifiers.Static; return modifiers; } // 生成方法逻辑替换为如下实现 public static string GenerateMethod() { using var workspace = new AdhocWorkspace(); var project = GetProject(workspace); var type = project.GetCompilationAsync().Result?.GetTypeByMetadataName(typeof(GenerationDemo).FullName); var method = type.GetMembers(nameof(Test)).Cast<IMethodSymbol>().Single(); var generator = SyntaxGenerator.GetGenerator(project); // 手动构造参数列表 var parameters = new List<SyntaxNode>(); foreach (var param in method.Parameters) { var flags = ParameterFlags.None; if (param.IsParams) flags |= ParameterFlags.Params; // 需要处理ref/in/out等修饰符也可在这里补充判断 SyntaxNode defaultValue = null; if (param.HasExplicitDefaultValue) { defaultValue = generator.LiteralExpression(param.ExplicitDefaultValue); } parameters.Add(generator.ParameterDeclaration( param.Name, generator.TypeExpression(param.Type), accessibility: Accessibility.NotApplicable, modifiers: flags, initializer: defaultValue)); } // 手动构造方法节点 var methodNode = generator.MethodDeclaration( method.Name, parameters, method.TypeParameters, returnType: generator.TypeExpression(method.ReturnType), accessibility: method.DeclaredAccessibility, modifiers: GetMethodModifiers(method)); return methodNode.NormalizeWhitespace().ToFullString(); }
相关说明
目前官方没有公开的完整文档列出SyntaxGenerator所有不支持的特性,除了params修饰符、可选参数默认值之外,常见的不支持生成的特性还包括:
- 参数上的
ref/in/out/ref readonly修饰符 - 参数、方法、类上的Attribute
- 泛型参数的复杂约束(仅支持基础类型约束、
new()约束等简单场景) - unsafe上下文相关修饰符
- C#独有的新增语法特性(比如init-only属性、主构造函数、集合表达式等)
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

