Skip to content

GetCustomAttributes throws Exception when attribute contains a type defined in a dynamic assembly. #101343

Open
@ceresgalax

Description

@ceresgalax

Description

When GetCustomAttributes<T>() is called on a type defined in a dynamic assembly created with AssemblyBuilder which has a custom attribute referencing another type in the dynamic assembly, a System.IO.FileNotFoundException exception is thrown.

Also note that when adding a Resolve callback to the AppDomain or ApplicationLoadContext and returning the AssemblyBuilder that contains the dynamic assembly, an exception will be thrown: System.InvalidOperationException: Dynamically emitted assemblies are unsupported during host-based resolution., so this is not a possible workaround.

Reproduction Steps

using System.Reflection;
using System.Reflection.Emit;

namespace ReproDAGetCustomAttributes;

[AttributeUsage(AttributeTargets.Class)]
public class MyCustomAttribute(Type type) : Attribute
{
    private readonly Type _type = type;
}

public static class Entry
{
    public static void Main()
    {
        AssemblyName an = new("MyDnamicAssembly");
        AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndCollect);
        ModuleBuilder mb = ab.DefineDynamicModule(an.Name!);
        
        TypeBuilder typeABuilder = mb.DefineType("TypeA", TypeAttributes.Class | TypeAttributes.Public);
        Type typeA = typeABuilder.CreateType();

        TypeBuilder typeBBuilder = mb.DefineType("TypeB", TypeAttributes.Class | TypeAttributes.Public);
        CustomAttributeBuilder cab = new(typeof(MyCustomAttribute).GetConstructor([typeof(Type)])!, [typeA]);
        typeBBuilder.SetCustomAttribute(cab);
        Type typeB = typeBBuilder.CreateType();
        
        typeB.GetCustomAttributes<MyCustomAttribute>(); // Throws exception
    }
}

Expected behavior

typeB.GetCustomAttributes should not throw an exception, and should return an instance of MyCustomAttribute constructed with the type of TypeA from the dynamic assembly.

Actual behavior

An exception is thrown when attempting to get the custom attributes of TypeB:

System.IO.FileNotFoundException: Could not load file or assembly 'MyDnamicAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
File name: 'MyDnamicAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
   at System.Reflection.RuntimeAssembly.InternalLoad(AssemblyName assemblyName, StackCrawlMark& stackMark, AssemblyLoadContext assemblyLoadContext, RuntimeAssembly requestingAssembly, Boolean throwOnFileNotFound)
   at System.Reflection.TypeNameParser.ResolveAssembly(String assemblyName)
   at System.Reflection.TypeNameParser.GetType(String typeName, ReadOnlySpan`1 nestedTypeNames, String assemblyNameIfAny)
   at System.Reflection.TypeNameParser.Parse()
   at System.Reflection.TypeNameParser.GetTypeHelper(Char* pTypeName, RuntimeAssembly requestingAssembly, Boolean throwOnError, Boolean requireAssemblyQualifiedName)
   at System.Reflection.CustomAttribute._CreateCaObject(RuntimeModule pModule, RuntimeType type, IRuntimeMethodInfo pCtor, Byte** ppBlob, Byte* pEndBlob, Int32* pcNamedArgs)
   at System.Reflection.CustomAttribute.AddCustomAttributes(ListBuilder`1& attributes, RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1 derivedAttributes)
   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeType type, RuntimeType caType, Boolean inherit)
   at System.Attribute.GetCustomAttributes(MemberInfo element, Type attributeType, Boolean inherit)
   at System.Reflection.CustomAttributeExtensions.GetCustomAttributes[T](MemberInfo element)
   at ReproDAGetCustomAttributes.Entry.Main()

Regression?

No response

Known Workarounds

No response

Configuration

Tested with .NET 8.0.0, & 8.0.1
Windows 10 (x64) & macOS 14.3.1 (23D60) (ARM64)

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions