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();
}
}
}
}
Код: Выделить всё
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
Мобильная версия