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

.NET5环境下运行时GetCustomAttribute返回null问题求解

问题描述

我有一段加载程序集并通过属性对数据进行分类的代码。
我尝试获取实际的CustomAttribute对象,在.NET Framework下调试时代码可正常返回对应值,在.NET5环境下运行时该方法返回null。

补充说明1

查阅官方文档后发现:

.NET Framework version 2.0 provides a new load context, the reflection-only context, which can be used to examine code that cannot be loaded for execution.

补充说明2

经排查问题原因为:我尝试在运行时获取属性对象,属性以及其他仅反射上下文中的运行时内容无法被加载,因此方法返回null。

核心疑问

请问除了使用System.Reflection外,还有什么其他方案可以在运行时获取到实际的属性对象?


相关代码

字典初始化代码

var ass = Assembly.LoadFile(Path.GetFullPath("MyInterface.dll"));
var asss = Assembly.GetExecutingAssembly();
var apiInterfaces = ass.DefinedTypes.Where(x => x.IsInterface && x.CustomAttributes != null && x.CustomAttributes.Any(z => z.AttributeType.FullName != null && z.AttributeType.FullName.Equals(typeof(ApiInterfaceDescriptorAttribute).FullName)));

自定义属性定义

[AttributeUsage(AttributeTargets.Interface)]
public class ApiInterfaceDescriptorAttribute : Attribute
{
    public string ApiUsageName { get; }

    public ApiInterfaceDescriptorAttribute(string apiUsageName)
    {
        ApiUsageName = apiUsageName;
    }
}

示例接口代码

[ApiInterfaceDescriptor("powercontrol")]
public interface IMyInterface 
{
   [ApiMethodDescriptor(ApiExposureLevel.Basic, "a-method...")]
    void SomeMethod();
}

获取属性的代码片段

public class ApiDetector
{
    private Dictionary<Type, List<MethodInfo>> _apiDictionary = new Dictionary<Type, List<MethodInfo>>();
    public void LoadApiElements()
    {
        var apiKeyDesriptor = key.GetCustomAttribute(typeof(ApiInterfaceDescriptorAttribute)) as ApiInterfaceDescriptorAttribute;
            _apiDetector.Add(new ApiDataObjectDescriptor { Name = key.Name, ApiUsageName = apiKeyDesriptor?.ApiUsageName, Type = key });
    }

}

运行效果
  • 本地运行可正常获取属性实例:
    本地运行结果
  • .NET5远程机器运行返回null:
    远程运行结果

解决思路
  1. 修正程序集加载逻辑
    该问题本质是.NET5+与.NET Framework的程序集加载上下文差异导致的,Assembly.LoadFile会将程序集加载到独立上下文,和当前执行域的Attribute类型不匹配,才会返回null。直接改用Assembly.LoadFrom替代LoadFile,程序集将加载到当前上下文,属性类型匹配后即可正常获取实例。

  2. 仅反射上下文兼容方案
    如果必须使用仅反射上下文加载程序集,可以直接读取CustomAttributeData的构造参数,手动构造Attribute实例,不需要依赖类型匹配即可拿到属性值,示例代码如下:

var attrData = x.CustomAttributes.First(z => z.AttributeType.FullName == typeof(ApiInterfaceDescriptorAttribute).FullName);
var descriptor = new ApiInterfaceDescriptorAttribute(attrData.ConstructorArguments[0].Value.ToString());

该方案不需要调整现有反射逻辑框架,即可拿到期望的属性值。

  1. 编译期预生成映射方案
    如果要完全规避运行时反射的上下文问题,可以使用Source Generator在编译期扫描所有标记了目标属性的接口,生成静态的属性映射字典,运行时直接读取字典即可,性能也优于运行时反射,适合对启动速度有要求的场景。

内容的提问来源于stack exchange,提问作者Michael Gabbay

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 00:54:06