zoukankan      html  css  js  c++  java
  • 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;
                        }
                    }
                }
            }
        }
    }
  • 相关阅读:
    项目中看似很难的问题可能很简单
    ASP.NET数据列表“全选”,批量处理的JS实现
    [转]给网站增加如:flv,torrent等特殊后缀格式文件下载
    GD Graphics Library
    在VS2008中编译64位程序以及遇到的问题
    关于C#闭包
    SNMP协议介绍及SNMP library
    ASP.NET MVC 使用总结(二)——扩展HtmlHelper实现动态生成title及meta
    LINQ查询代码整理(一)
    使用方便的SDK帮助文档
  • 原文地址:https://www.cnblogs.com/zhurongbo/p/10423231.html
Copyright © 2011-2022 走看看