C# 自定义AssemblyLoadContext无法加载Microsoft.AspNetCore.Components
编辑:我已将该问题的源代码上载到GitHub,如果您想下载: 我有一个.NET Core 3.0控制台应用程序,它引用了一个带有单个接口的.NET标准2.0类库(IModule)。我还有一个ASP.NET Core 3.0应用程序,它引用了相同的.NET标准2.0类库并实现了接口(模块:IModule) 我正在尝试使用自定义AssemblyLoadContext和公共类库接口(IModule)从.NET Core控制台应用程序加载ASP.NET Core程序集。。。一个简单的插件系统 不幸的是,ASP.NET核心模块/插件在加载(AssemblyName)的ALC覆盖功能中失败,出现以下异常: 无法加载文件或程序集“Microsoft.AspNetCore.Components,版本=3.0.0.0,区域性=中性,PublicKeyToken=adb9793829ddae60”。系统找不到指定的文件。 当我尝试使用不同的项目类型(例如.NET核心控制台应用程序或.NET标准2.0类库)时,模块/插件会按预期加载 以下是控制台应用程序代码:C# 自定义AssemblyLoadContext无法加载Microsoft.AspNetCore.Components,c#,asp.net-core,.net-core,C#,Asp.net Core,.net Core,编辑:我已将该问题的源代码上载到GitHub,如果您想下载: 我有一个.NET Core 3.0控制台应用程序,它引用了一个带有单个接口的.NET标准2.0类库(IModule)。我还有一个ASP.NET Core 3.0应用程序,它引用了相同的.NET标准2.0类库并实现了接口(模块:IModule) 我正在尝试使用自定义AssemblyLoadContext和公共类库接口(IModule)从.NET Core控制台应用程序加载ASP.NET Core程序集。。。一个简单的插件系统 不幸的是,
using NetStandardCommon;
using System;
using System.IO;
namespace NetCoreConsoleApp
{
class Program
{
static void Main(string[] args)
{
LoadNetCoreModule();
LoadAspNetCoreModule();
}
static void LoadNetCoreModule()
{
//Works!
FileInfo asm = new FileInfo(@"..\..\..\..\NetCoreModule\bin\debug\netcoreapp3.0\NetCoreModule.dll");
var moduleDirectory = asm.DirectoryName;
ModuleAssemblyLoadContext context = new ModuleAssemblyLoadContext(asm.Name, moduleDirectory, typeof(IModule));
context.Scan();
foreach (var module in context.GetImplementations<IModule>())
{
module.Start();
}
}
static void LoadAspNetCoreModule()
{
//Fails!
FileInfo asm = new FileInfo(@"..\..\..\..\AspNetCoreApp\bin\debug\netcoreapp3.0\AspNetCoreApp.dll");
var moduleDirectory = asm.DirectoryName;
ModuleAssemblyLoadContext context = new ModuleAssemblyLoadContext(asm.Name, moduleDirectory, typeof(IModule));
context.Scan();
foreach (var module in context.GetImplementations<IModule>())
{
module.Start();
}
}
}
}
对于为.net核心插件系统加载/卸载程序集的可能性,我感到很兴奋,但我正在努力克服这个障碍。我缺少什么?大约一个月前,我在将程序集加载到SQL server时遇到了这个问题。是否使用虚拟驱动器存储程序集?我发现我们的共享驱动器实际驱动器路径是E驱动器,而不是映射到我的计算机上的P驱动器。我实际上是连接到它的,所以我必须给出真正的驱动器路径,该路径以E而不是P开头。此外,您的程序可能也将其映射到了错误的驱动器。我会检查这一点,如果这对我没有帮助的话,我还有3-4件事情要做,以解决这个问题 大约一个月前,我在将程序集加载到SQL server时遇到了这个问题。是否使用虚拟驱动器存储程序集?我发现我们的共享驱动器实际驱动器路径是E驱动器,而不是映射到我的计算机上的P驱动器。我实际上是连接到它的,所以我必须给出真正的驱动器路径,该路径以E而不是P开头。此外,您的程序可能也将其映射到了错误的驱动器。我会检查这一点,如果这对我没有帮助的话,我还有3-4件事情要做,以解决这个问题 我相信库可能还需要在目标框架设置为.NetCore 3.0(netcoreapp3.0)的情况下构建。我相信库可能还需要在目标框架设置为.NetCore 3.0(netcoreapp3.0)的情况下构建。想法不错,但所有项目/程序集都在本地C驱动程序上,但是所有项目/程序集都在本地C驱动器上。我尝试将公共库(ClassLibrary1)切换到目标netcoreapp3.0,而不是netstandard2.0。不幸的是,出现了相同的错误。我尝试将公共库(ClassLibrary1)切换到目标netcoreapp3.0,而不是netstandard2.0。不幸的是,同样的错误也发生了。
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.Loader;
using System.Linq;
namespace NetCoreConsoleApp
{
public class ModuleAssemblyLoadContext : AssemblyLoadContext
{
private List<Assembly> _loaded;
private Dictionary<string, Assembly> _shared;
private string _path;
private AssemblyDependencyResolver _resolver;
public ModuleAssemblyLoadContext(string name, string path, params Type[] sharedTypes) : base(name)
{
_path = path;
_resolver = new AssemblyDependencyResolver(_path);
_loaded = new List<Assembly>();
_shared = new Dictionary<string, Assembly>();
if (sharedTypes != null)
{
foreach (Type sharedType in sharedTypes)
{
_shared[Path.GetFileName(sharedType.Assembly.Location)] = sharedType.Assembly;
}
}
}
public void Scan()
{
foreach (string dll in Directory.EnumerateFiles(_path, "*.dll"))
{
var file = Path.GetFileName(dll);
if (_shared.ContainsKey(file))
{
continue;
}
var asm = this.LoadFromAssemblyPath(dll);
_loaded.Add(asm);
}
}
public IEnumerable<T> GetImplementations<T>()
{
return _loaded
.SelectMany(a => a.GetTypes())
.Where(t => typeof(T).IsAssignableFrom(t))
.Select(t => Activator.CreateInstance(t))
.Cast<T>();
}
protected override Assembly Load(AssemblyName assemblyName)
{
string filename = $"{assemblyName.Name}.dll";
if (_shared.ContainsKey(filename))
{
return _shared[filename];
}
string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
if (assemblyPath != null)
{
return LoadFromAssemblyPath(assemblyPath);
}
return null;
}
protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
{
string libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
if (libraryPath != null)
{
return LoadUnmanagedDllFromPath(libraryPath);
}
return IntPtr.Zero;
}
}
}
protected override Assembly Load(AssemblyName assemblyName)
{
string filename = $"{assemblyName.Name}.dll";
if (_shared.ContainsKey(filename))
{
return _shared[filename];
}
try
{
if (File.Exists(@"C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App\3.0.0\" + filename))
{
return Assembly.LoadFrom(@"C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App\3.0.0\" + filename);
}
}
catch (Exception ex)
{
//Message displayed is 'An attempt was made to load a program with an incorrect format. (0x8007000B)'
Console.WriteLine(ex.Message);
}
return Assembly.Load(assemblyName);
}