net core手动加载dll,无法自动加载其依赖项

用的net core版本是2.1,也许在后续的版本中已经修复了这个问题

今天在尝试用net core写demo的时候,发现了这个问题。因为都是使用DI,所以就没有我的网站项目里直接引用一些实现类库,而是放到了同一个目录下,在网站启动的时候用代码去加载进来。然而在实际的运行过程成中发现,指定的dll会自动加载,但是其依赖的nuget包里的dll不会被加载进来,在Google了很久,也发现了很多人提出过这个问题,在GitHub上也有人提过https://github.com/dotnet/corefx/issues/21982,但是都没有直接的解决方案,其中有一个差不多的解决方案https://www.codeproject.com/Articles/1194332/Resolving-Assemblies-in-NET-Core,我的解决方案也是依据这个改进而来的。

代码的核心思路是去找需要手动加载的DLL的依赖项,尝试去找到该依赖项所在的位置,然后再加载进来。详细代码如下:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.DependencyModel.Resolution;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using ZRB.Blog.Configurations;

namespace ZRB.Blog.Injection
{
    public static class AssemblyLoader
    {
        private static readonly ICompilationAssemblyResolver AssemblyResolver;
        private static readonly ConcurrentDictionary<string, CompilationLibrary> DependencyDLL;

        static AssemblyLoader()
        {
            AssemblyLoadContext.Default.Resolving += Default_Resolving;
            AssemblyResolver = new CompositeCompilationAssemblyResolver(
                new ICompilationAssemblyResolver[]{
                    new AppBaseCompilationAssemblyResolver(AppDomain.CurrentDomain.BaseDirectory),
                    new ReferenceAssemblyPathResolver(),
                    new PackageCompilationAssemblyResolver()
                });
            DependencyDLL = new ConcurrentDictionary<string, CompilationLibrary>();
        }

        private static Assembly Default_Resolving(AssemblyLoadContext assemblyLoadContext, AssemblyName assemblyName)
        {
            if(DependencyDLL.ContainsKey(assemblyName.Name))
            {
                var compilationLibrary = DependencyDLL[assemblyName.Name];
                var assemblies = new List<string>();
                if (AssemblyResolver.TryResolveAssemblyPaths(compilationLibrary, assemblies) && assemblies.Count > 0)
                {
                    var assembly = assemblyLoadContext.LoadFromAssemblyPath(assemblies[0]);
                    FindDependency(assembly);
                    return assembly;
                }
            }
            return null;

        }

        public static Assembly GetAssembly(string assemblyName)
        {
            string assemblyFileName = AppDomain.CurrentDomain.BaseDirectory + assemblyName + ".dll";
            Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName?.Split(',')[0] == assemblyName) ?? AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyFileName);
            FindDependency(assembly);
            return assembly;
        }

        private static void FindDependency(Assembly assembly)
        {
            DependencyContext dependencyContext = DependencyContext.Load(assembly);
            if(dependencyContext!= null)
            {
                foreach (var compilationLibrary in dependencyContext.CompileLibraries)
                {
                    if (!DependencyDLL.ContainsKey(compilationLibrary.Name)
                    && !AppDomain.CurrentDomain.GetAssemblies().Any(a => a.FullName.Split(',')[0] == compilationLibrary.Name))
                    {
                        RuntimeLibrary library = dependencyContext.RuntimeLibraries.FirstOrDefault(runtime => runtime.Name == compilationLibrary.Name);
                        var cb = new CompilationLibrary(
                            library.Type,
                            library.Name,
                            library.Version,
                            library.Hash,
                            library.RuntimeAssemblyGroups.SelectMany(g => g.AssetPaths),
                            library.Dependencies,
                            library.Serviceable);

                        DependencyDLL[library.Name] = cb;
                    }
                }
            }
        }
    }
}
原文地址:https://www.cnblogs.com/zhurongbo/p/10423231.html