Невозможно перезагрузить dll C# из C#C#

Место общения программистов C#
Ответить
Anonymous
 Невозможно перезагрузить dll C# из C#

Сообщение Anonymous »

Доброе утро. Я хочу перезагрузить dll во время выполнения, но не могу. У меня есть две программы, назовем их хост и плагин. Хост компилируется в исполняемый файл, а плагин компилируется в dll. Хост загружает функцию из плагина во время выполнения, я вношу изменения в плагин и перекомпилирую его. А затем на хосте я хочу перезагрузить dll плагина и использовать обновленную функцию без необходимости перезапуска хост-программы. я создал небольшой пример, где существует эта проблема. Для справки вот код:
Host.cs:

Код: Выделить всё

using System;
using System.Reflection;
using System.Runtime.Loader;

namespace Host {
public class PluginAssemblyLoadContext : AssemblyLoadContext {
public PluginAssemblyLoadContext() : base(true) { }
}

public class HostState {
public Assembly                  pluginAssembly;
public PluginAssemblyLoadContext   loadContext;
public Action                    pluginExecute;
}

public static class Host {
public const string PLUGIN_PATH = "../plugin/bin/Debug/net9.0/plugin.dll";

public static void Main() {
HostState host = new HostState();
host.loadContext = new PluginAssemblyLoadContext();
ReloadDll(host);

Console.WriteLine("Press E to execute the plugin, R to reload, or Q to quit.");

for (;;) {
var key = Console.ReadKey(true);
if (false) {
} else if (key.Key == ConsoleKey.E) {
host.pluginExecute.Invoke();
} else if (key.Key == ConsoleKey.R) {
ReloadDll(host);
} else if (key.Key == ConsoleKey.Q) {
return;
}
}
}

public static void ReloadDll(HostState host) {
host.pluginAssembly = null;
host.pluginExecute = null;

GC.Collect();
GC.WaitForPendingFinalizers();

host.loadContext?.Unload();

GC.Collect();
GC.WaitForPendingFinalizers();

host.loadContext = new PluginAssemblyLoadContext();
host.pluginAssembly = host.loadContext.LoadFromAssemblyPath(Path.GetFullPath(PLUGIN_PATH));

Type type = host.pluginAssembly.GetType("Plugin");
MethodInfo methodInfo = type.GetMethod("Execute", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, []);

if (methodInfo != null) {
host.pluginExecute = methodInfo.CreateDelegate();
}
}
}
}
Plugin.cs:

Код: Выделить всё

using System;

public static class Plugin {
public static void Execute() {
Console.WriteLine("1");
}
}
Сценарий
Я запускаю хост-программу. Я нажимаю E, чтобы запустить плагин. Я получил результат «1». Я захожу в Plugin.cs. Я меняю функцию Execute() для вывода «2» вместо «1», а затем пересобираю проект плагина. Я возвращаюсь к терминалу, на котором работает хост-программа. Я нажимаю R, а затем нажимаю E.

Что происходит

Я снова получил результат «1».

Что должно было произойти

Вместо этого я должен был получить результат «2».

Что я пробовал

  • Я пытался установить значение null для каждой ссылки, полученной из PluginAssemblyLoadContext, как упомянуто в третьем примечании документации ms.
  • Я пытался изменить версию сборки при сборке плагина.dll, но это тоже не помогло.
  • Вызвал GC.Collect() и GC.WaitForPendingFinalizers(), чтобы убедиться, что каждая ссылка собирает мусор.

Почему я хочу для этого

У меня есть игровой движок, и я хочу иметь возможность перезагрузить игровую dll без необходимости перезапускать редактор движка. Таким образом, в этом случае хостом будет редактор движка, а плагином будет игра.

Характеристики

  • ЦП: x86-64
  • os: debian sid
  • версия dotnet sdk: 9.0.305
-
Есть идеи, как перезагрузить dll во время выполнения? Любая помощь будет оценена по достоинству.

Подробнее здесь: https://stackoverflow.com/questions/797 ... om-c-sharp
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»