Динамическая загрузка DLL с зависимостью, а затем ее выгрузка, по-прежнему блокируем DLL, и я не могу удалить / заменить dll.
В рамках написания приложения-плагина я динамически загружаю DLL (которая имеет зависимость, например, Newtonsoft.Json), запускаю загруженную сборку и затем выгружаю ее. после выгрузки я не могу удалить DLL с диска (пока я не перезапущу свое приложение), НО, если я использую DLL, у которой нет зависимостей, она работает нормально и не блокирует файл. Реализация основана на загрузке / выгрузке ядра .NET 3, взятых из: 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);
....
....
}