简体   繁体   English

GetCustomAttribute 在 .NET5 上的运行时返回 null

[英]GetCustomAttribute returns null in runtime on .NET5

I have a code that loads an assembly and categorize data by attributes.我有一个加载程序集并按属性对数据进行分类的代码。

I'm trying to get the actual CustomAttribute object.我正在尝试获取实际的 CustomAttribute 对象。 During debug on net framework, the code returns a value.在网络框架上调试期间,代码返回一个值。 Running the code on .Net5 returns null在 .Net5 上运行代码返回 null

Edit After some digging in documentation:在对文档进行一些挖掘后进行编辑

.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. .NET Framework 2.0 版提供了一个新的加载上下文,即仅反射上下文,可用于检查无法加载执行的代码。

https://docs.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/accessing-custom-attributes https://docs.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/accessing-custom-attributes

Edit #2 The reason is that i'm trying to get the object during runtime, and as written in the documentaion quote above, the attribute as well as any other runtime reflection-only context is cannot be loaded, and the method returns null.编辑 #2原因是我试图在运行时获取对象,并且如上面的文档引用中所述,无法加载该属性以及任何其他仅运行时反射的上下文,并且该方法返回 null。

Is there any other solution other than using system.reflection to get the an actual attribute object on runtime?除了使用 system.reflection 在运行时获取实际属性对象之外,还有其他解决方案吗?

The dictionary initialization字典初始化

        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)));
        

The Attribute:属性:

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

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

Sample interface示例界面

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

The trial to get the attribute获取属性的试用

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 });
    }

}

when i ran this code locally i get the instance:当我在本地运行此代码时,我得到了实例: 在此处输入图片说明

Running the code on .Net5 remote machine returns null:在 .Net5 远程机器上运行代码返回 null:

在此处输入图片说明

Any help will be welcome.欢迎任何帮助。 Thanks ahead!先谢谢了!

The root cause is the call to Assembly.LoadFile.根本原因是对 Assembly.LoadFile 的调用。 This method always loads the specified assembly into its own AssemblyLoadContext.此方法始终将指定的程序集加载到其自己的 AssemblyLoadContext 中。 (More about assembly load context). (更多关于程序集加载上下文)。

This means that you have the assembly loaded into the LoadFile load context (one copy) and I have a direct reference to it from your main code, which will load it into the default load context (second copy).这意味着您已将程序集加载到 LoadFile 加载上下文(一个副本)中,并且我从您的主代码中直接引用了它,这会将它加载到默认加载上下文(第二个副本)中。 While the assembly file is exactly the same, for the runtime these two copies are distinct assemblies and all types from the two will be treated as different types.虽然程序集文件完全相同,但对于运行时来说,这两个副本是不同的程序集,两者中的所有类型都将被视为不同的类型。

changing the assembly load method to:将程序集加载方法更改为:

Assembly.GetAssembly(typeof(MyType));

have resolved the problem.已经解决了问题。

thanks to vitek-karas from Microsoft support team.感谢 Microsoft 支持团队的 vitek-karas。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM