Skip to content

Returning Assembly from collectible LoadAssemblyContext via AssemblyResolve event handler #49132

@BaHXeLiSiHg

Description

@BaHXeLiSiHg

Greetings! Using Core 3.0 with collectible AssemblyLoadContext, in order to unload/reload dynamically loaded assemblies on demand.

I'm not sure if it's bug or a misunderstanding of AssemblyResolve event handler, let me try to explain:

I have configured cache of dynamically loading/reloading/unloading assemblies, separate collectible AssemblyLoadContext per loaded assembly. Everything works perfect, but i have encountered issues with 3-rd party library.

This 3-rd party library have serialization logic in some parts of code flow, using kind of BinarySerializer extension which is trying to access types from any of mine dynamically loaded assembly by standard Type.GetType(string typeName) method. Such behavior throwing errors because types of dynamically loaded assembly are not in AppDomain.CurrentDomain but in separate collectible AssemblyLoadContext.

To save supporting of this 3-rd party library, i have added AssemblyResolve event handler, to guide system where it should looking for assembly:

AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolveEventHandler;

Where handler looks like:

private static Assembly AssemblyResolveEventHandler(object sender, ResolveEventArgs resolveEvent)
{
    var dynamicPartsManager = StaticServiceProvider.Stash.GetService<IDynamicPartsManager>();

    if (dynamicPartsManager.DynamicAssemblyLoaded)
    {
        var assemblyFriendlyName = resolveEvent.Name.Substring(
            0,
            resolveEvent.Name.IndexOf(",", StringComparison.InvariantCultureIgnoreCase)
        );

        if (DynamicAssemblyLoader.HasLoadedDomain(assemblyFriendlyName, out AssemblyLoadContext domain))
        {
            var dynamicAssembly = domain.Assemblies.FirstOrDefault(assembly => assembly.FullName == resolveEvent.Name);

            return dynamicAssembly;
        }
    }

    return null;
}

Where DynamicAssemblyLoader is my cache of dynamically loaded assemblies per AssemblyLoadContext.

When looking assembly was successfully found and returned it throws exception:

System.IO.FileLoadException: Could not load file or assembly 'MyDynamicAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. Operation is not supported. (0x80131515)
File name: 'MyDynamicAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
 ---> System.NotSupportedException: Resolving to a collectible assembly is not supported.
   at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, StackCrawlMarkHandle stackMark, ObjectHandleOnStack assemblyLoadContext, Boolean loadTypeFromPartialName, ObjectHandleOnStack type, ObjectHandleOnStack keepalive)
   at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, StackCrawlMark& stackMark, AssemblyLoadContext assemblyLoadContext, Boolean loadTypeFromPartialName)
   at System.RuntimeType.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, StackCrawlMark& stackMark)
   at System.Type.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase)
   ...
   3-rd party library call stack

Probably it is not possible to "just return" found Assembly or am i doing something wrong?

If anybody have any suggestions - please, share them, cause i'm out of ideas :(

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions