Загрузка, а затем выгрузка DLL с зависимостью блокирует DLL

Динамическая загрузка 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);
    ....
    ....
}

person toto    schedule 26.09.2019    source источник
comment
У вас есть новости по этому поводу? потому что я также ищу решение для этого   -  person Justin99b    schedule 24.12.2019
comment
@ Justin99b Я ответил на свой вопрос, это тебе и всем остальным :)   -  person toto    schedule 24.12.2019


Ответы (1)


Проблема решена, в основном при выгрузке DLL вы не можете этого сделать, если у вас есть зависимость Newtonsoft.Json, потому что у них есть ошибка, которая блокирует файл.

Это основано на ответе на проблему с github, которую я открыл

person toto    schedule 24.12.2019