使用Roslyn API查询类自定义属性时GetAttributes()为空,如何解决?
Roslyn查询程序集类自定义属性的正确姿势
没问题,Roslyn完全支持加载已编译程序集并查询类的自定义属性,你遇到GetAttributes()返回空的情况,大概率是实现过程中忽略了一些关键细节,下面我帮你拆解问题并给出正确的实现方式:
常见问题原因
- 混淆了Roslyn的符号系统和.NET的反射系统:Roslyn的
GetAttributes()是针对INamedTypeSymbol这类语义符号的,如果你直接用反射获取类型再转成Roslyn符号,或者没有正确通过Compilation解析程序集元数据,就会导致无法获取属性。 - 加载程序集时没有正确创建
MetadataReference,导致编译上下文无法访问目标程序集的元数据。 - 目标自定义属性的访问级别(比如
internal)导致当前编译上下文无法解析到它。
正确实现步骤&代码示例
下面是完整的加载程序集并查询类自定义属性的代码:
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using System; using System.Linq; // 替换为你的目标程序集路径 var targetAssemblyPath = @"D:\Projects\YourProject\bin\Release\net6.0\YourAssembly.dll"; // 1. 创建程序集的元数据引用 var metadataRef = MetadataReference.CreateFromFile(targetAssemblyPath); // 2. 创建临时编译上下文(Roslyn需要通过Compilation来解析符号) var compilation = CSharpCompilation.Create("TempAssemblyAnalysis") .AddReferences(metadataRef); // 3. 获取程序集的符号表示 var assemblySymbol = compilation.GetAssemblySymbol(metadataRef); if (assemblySymbol == null) { Console.WriteLine("无法加载目标程序集符号"); return; } // 4. 查找目标类的符号(替换为你的命名空间和类名) var targetClassSymbol = assemblySymbol.GlobalNamespace .GetTypeMembers("YourNamespace.TargetClass") .FirstOrDefault(); if (targetClassSymbol != null) { // 5. 获取类的所有自定义属性 var classAttributes = targetClassSymbol.GetAttributes(); if (classAttributes.Any()) { Console.WriteLine($"找到 {classAttributes.Count()} 个自定义属性:"); foreach (var attribute in classAttributes) { Console.WriteLine($"- 属性类型:{attribute.AttributeClass.Name}"); // 可选:获取属性的构造函数参数 if (attribute.ConstructorArguments.Any()) { Console.WriteLine(" 构造参数:"); foreach (var arg in attribute.ConstructorArguments) { Console.WriteLine($" - {arg.Value} ({arg.Type.Name})"); } } } } else { Console.WriteLine("未找到任何自定义属性,请确认类上确实标记了属性,且属性可被当前上下文访问"); } } else { Console.WriteLine("未找到目标类,请检查命名空间和类名是否正确"); }
额外注意事项
- 如果你的自定义属性是
internal访问级别,可以在创建MetadataReference时添加访问权限配置:var metadataRef = MetadataReference.CreateFromFile( targetAssemblyPath, MetadataReferenceProperties.Default.WithAccessibility(Accessibility.Internal) ); - 如果你是要分析源代码中的类属性(而非已编译程序集),流程会不同:需要先解析语法树,再通过语义模型获取类型符号,再调用
GetAttributes()。
内容的提问来源于stack exchange,提问作者VKR
相关产品推荐
相关产品推荐

