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;
                    }
                }
            }
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM