You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:20:31