简体   繁体   中英

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. During debug on net framework, the code returns a value. Running the code on .Net5 returns 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.

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.

Is there any other solution other than using system.reflection to get the an actual attribute object on runtime?

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:

在此处输入图片说明

Any help will be welcome. Thanks ahead!

The root cause is the call to Assembly.LoadFile. This method always loads the specified assembly into its own 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). 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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