• 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;
                        }
                    }
                }
            }
        }
    }
  • 相关阅读:
    记录使用cx_Freeze打包Python成exe可执行程序
    jquery plug-in DataTable API中文文档参考
    java.lang.UnsatisfiedLinkError: dlopen failed: /data/app/xxx/lib/arm/liblame.so: has text relocations
    CocoaPods的安装及使用
    Android 贝塞尔曲线的浅析
    GUI学习中错误Exception in thread "main" java.lang.NullPointerException
    线程
    12月13日
    今天开始学习java编程
    UVA10140 Prime Distance
  • 原文地址:https://www.cnblogs.com/zhurongbo/p/10423231.html
Copyright © 2020-2023  润新知