使用依赖项加载然后卸载 DLL 会锁定 DLL
Loading and then Unloading DLL with dependency locks the DLL
动态加载具有依赖关系的 DLL,然后卸载它,仍然锁定 DLL,我无法 delete/replace dll。
作为编写插件应用程序的一部分,我动态加载 DLL(具有依赖性,例如 Newtonsoft.Json),运行 加载的程序集,然后卸载它。卸载后,我无法从磁盘中删除 DLL(直到我重新启动我的应用程序),但是,如果我使用没有依赖项的 DLL,它可以正常工作,并且不会锁定文件.
该实现基于 .NET 核心 3 load/unload,取自:
https://docs.microsoft.com/en-us/dotnet/standard/assembly/unloadability
我使用的 AssemblyLoadContext
有解析器,例如:
class TestAssemblyLoadContext : AssemblyLoadContext
{
private AssemblyDependencyResolver _resolver;
public TestAssemblyLoadContext(string mainAssemblyToLoadPath) : base(isCollectible: true)
{
_resolver = new AssemblyDependencyResolver(mainAssemblyToLoadPath);
}
protected override Assembly Load(AssemblyName name)
{
string assemblyPath = _resolver.ResolveAssemblyToPath(name);
if (assemblyPath != null)
{
return LoadFromAssemblyPath(assemblyPath);
}
return null;
}
}
以及创建上下文的代码:
[MethodImpl(MethodImplOptions.NoInlining)]
public static void runCommands(string pluginPath, bool execute,out WeakReference alcWeakRef)
{
string pluginLocation = getPath(pluginPath);
PluginLoadContext loadContext = new PluginLoadContext(pluginLocation);
alcWeakRef = new WeakReference(loadContext, trackResurrection: true);
Assembly pluginAssembly = loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(pluginLocation)));
var commands = CreateCommands(pluginAssembly).ToList();
if (execute) {
Console.WriteLine("Commands: ");
foreach (ICommand command in commands)
{
Console.WriteLine($"executing... {command.Execute()}");
}
}
commands.Clear();
loadContext.Unload();
}
我想知道这是不是我做错了什么,我已经尝试从流中加载文件,例如:
using (var fs = new FileStream(pluginLocation, FileMode.Open, FileAccess.Read))
{
var pluginAssembly = loadContext.LoadFromStream(fs);
....
....
}
问题解决了,基本上在卸载DLL的时候,如果有Newtonsoft.Json依赖就不能卸载了,因为他们有一个锁文件的bug。
这是基于 github issue 我打开
的回复
动态加载具有依赖关系的 DLL,然后卸载它,仍然锁定 DLL,我无法 delete/replace dll。
作为编写插件应用程序的一部分,我动态加载 DLL(具有依赖性,例如 Newtonsoft.Json),运行 加载的程序集,然后卸载它。卸载后,我无法从磁盘中删除 DLL(直到我重新启动我的应用程序),但是,如果我使用没有依赖项的 DLL,它可以正常工作,并且不会锁定文件. 该实现基于 .NET 核心 3 load/unload,取自: https://docs.microsoft.com/en-us/dotnet/standard/assembly/unloadability
我使用的 AssemblyLoadContext
有解析器,例如:
class TestAssemblyLoadContext : AssemblyLoadContext
{
private AssemblyDependencyResolver _resolver;
public TestAssemblyLoadContext(string mainAssemblyToLoadPath) : base(isCollectible: true)
{
_resolver = new AssemblyDependencyResolver(mainAssemblyToLoadPath);
}
protected override Assembly Load(AssemblyName name)
{
string assemblyPath = _resolver.ResolveAssemblyToPath(name);
if (assemblyPath != null)
{
return LoadFromAssemblyPath(assemblyPath);
}
return null;
}
}
以及创建上下文的代码:
[MethodImpl(MethodImplOptions.NoInlining)]
public static void runCommands(string pluginPath, bool execute,out WeakReference alcWeakRef)
{
string pluginLocation = getPath(pluginPath);
PluginLoadContext loadContext = new PluginLoadContext(pluginLocation);
alcWeakRef = new WeakReference(loadContext, trackResurrection: true);
Assembly pluginAssembly = loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(pluginLocation)));
var commands = CreateCommands(pluginAssembly).ToList();
if (execute) {
Console.WriteLine("Commands: ");
foreach (ICommand command in commands)
{
Console.WriteLine($"executing... {command.Execute()}");
}
}
commands.Clear();
loadContext.Unload();
}
我想知道这是不是我做错了什么,我已经尝试从流中加载文件,例如:
using (var fs = new FileStream(pluginLocation, FileMode.Open, FileAccess.Read))
{
var pluginAssembly = loadContext.LoadFromStream(fs);
....
....
}
问题解决了,基本上在卸载DLL的时候,如果有Newtonsoft.Json依赖就不能卸载了,因为他们有一个锁文件的bug。
这是基于 github issue 我打开
的回复