Assembly Loading in .NET Core

前端 未结 2 940
眼角桃花
眼角桃花 2021-01-03 03:59

Using VS2017 RC, .NET Core

I am trying to load an assembly from a file. The dependencies of this assembly are in the same folder.

I am using AssemblyL

相关标签:
2条回答
  • 2021-01-03 04:35

    There is a great enhancement in .Net Core 3.0+, wire AssemblyLoadContext.Default.Resolving event as given below and all dependencies will be resolved and loaded:

     AssemblyLoadContext.Default.Resolving += (context, name) => {
                    string assemblyPath = $"{pluginFolder}\\{name.Name}.dll";                
                    if (assemblyPath != null)   
                        return context.LoadFromAssemblyPath(assemblyPath);     
                    return null;
                };
    

    Remember to define the variabe pluginFolder

    Solution2

    You can use the AssemblyDependencyResolver class and resolve dependendencies including ones in .deps.json:

      var resolver = new AssemblyDependencyResolver(pluginPath);            
    
      AssemblyLoadContext.Default.Resolving += (context, name) => {
    
                    string assemblyPath = resolver.ResolveAssemblyToPath(name);               
                    if (assemblyPath != null)   
                        return context.LoadFromAssemblyPath(assemblyPath);     
                    return null;
                };
    
    0 讨论(0)
  • 2021-01-03 04:57

    Well what works for me is to register a handle with the Resolving event and load required assemblies on demand when LoadFromAssemblyPath needs dependencies. Be aware that this my solution from hours of trial and error, so it might not be the most ideal way. It works for me by now though. Here's my code:

        AssemblyLoadContext.Default.Resolving += (context, name) =>
        {
            // avoid loading *.resources dlls, because of: https://github.com/dotnet/coreclr/issues/8416
            if (name.Name.EndsWith("resources"))
            {
                return null;
            }
    
            var dependencies = DependencyContext.Default.RuntimeLibraries;
            foreach (var library in dependencies)
            {
                if (IsCandidateLibrary(library, name))
                {
                    return context.LoadFromAssemblyName(new AssemblyName(library.Name));
                }
            }
    
            var foundDlls = Directory.GetFileSystemEntries(new FileInfo(<YOUR_PATH_HERE>).FullName, name.Name + ".dll", SearchOption.AllDirectories);
            if (foundDlls.Any())
            {
                return context.LoadFromAssemblyPath(foundDlls[0]);
            }
    
            return context.LoadFromAssemblyName(name);
        };
    }
    private static bool IsCandidateLibrary(RuntimeLibrary library, AssemblyName assemblyName)
    {
        return (library.Name == (assemblyName.Name))
                || (library.Dependencies.Any(d => d.Name.StartsWith(assemblyName.Name)));
    }
    

    The IsCandidateLibrary() bit originates from there: http://www.michael-whelan.net/replacing-appdomain-in-dotnet-core/

    I think you could omit this and the whole DependencyContext part, but it acts as a cache and avoids reloading the same assemblies over and over again. So i kept it.

    0 讨论(0)
提交回复
热议问题