diff --git a/.idea/.idea.FantasyNetTest/.idea/vcs.xml b/.idea/.idea.FantasyNetTest/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/.idea.FantasyNetTest/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FantasyNetTest/Form1.cs b/FantasyNetTest/Form1.cs
index 57d0849..a3a33bb 100644
--- a/FantasyNetTest/Form1.cs
+++ b/FantasyNetTest/Form1.cs
@@ -328,7 +328,7 @@ public partial class Form1 : Form
private void LoadProtocol()
{
Log.Info("开始加载协议");
- _scriptLoader.LoadAndExecuteScriptsAsync(_config.ProtocolScriptPath);
+ _scriptLoader.LoadAndExecuteScripts(_config.ProtocolScriptPath);
Log.Succeed("加载协议完成");
CoderLoader.Load();
SetProtocolComboBox();
diff --git a/FantasyNetTest/Loader/ScriptLoader.cs b/FantasyNetTest/Loader/ScriptLoader.cs
index 9b77cc8..0e2f121 100644
--- a/FantasyNetTest/Loader/ScriptLoader.cs
+++ b/FantasyNetTest/Loader/ScriptLoader.cs
@@ -1,22 +1,26 @@
using System;
-using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
-using System.Threading.Tasks;
-using FantasyNetTest;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Scripting;
-using Microsoft.CodeAnalysis.Scripting;
-using NBC;
public class ScriptLoader
{
- public void LoadAndExecuteScriptsAsync(string folderPath)
+ private AssemblyLoadContext _lastContext;
+
+ public void LoadAndExecuteScripts(string folderPath)
{
- // 1. 读取所有 .cs 文件
+ // 如果有旧的上下文,卸载它
+ if (_lastContext != null)
+ {
+ _lastContext.Unload();
+ _lastContext = null;
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+ }
+
var csFiles = Directory.GetFiles(folderPath, "*.cs", SearchOption.AllDirectories);
if (!csFiles.Any())
@@ -25,20 +29,20 @@ public class ScriptLoader
return;
}
- // 2. 创建语法树
var syntaxTrees = csFiles.Select(file =>
CSharpSyntaxTree.ParseText(File.ReadAllText(file))
);
- // 3. 引用程序集
var references = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => !a.IsDynamic && !string.IsNullOrWhiteSpace(a.Location))
.Select(a => MetadataReference.CreateFromFile(a.Location))
.Cast();
- // 4. 编译成内存程序集
+ // 每次给程序集一个唯一名字
+ string asmName = $"DynamicScripts_{Guid.NewGuid():N}";
+
var compilation = CSharpCompilation.Create(
- assemblyName: "DynamicScripts",
+ assemblyName: asmName,
syntaxTrees: syntaxTrees,
references: references,
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
@@ -54,14 +58,15 @@ public class ScriptLoader
return;
}
- // 5. 加载程序集
ms.Seek(0, SeekOrigin.Begin);
-
- var assembly = AssemblyLoadContext.Default.LoadFromStream(ms);
- // 6. 调用示例
- var type = assembly.GetType("MyNamespace.MyClass"); // 你的类名
- var method = type?.GetMethod("Run"); // 你的方法名
- method?.Invoke(null, null); // 假设是静态方法无参数
+ // 用可卸载的 AssemblyLoadContext 加载
+ var alc = new AssemblyLoadContext(asmName, isCollectible: true);
+ var assembly = alc.LoadFromStream(ms);
+ _lastContext = alc;
+
+ var type = assembly.GetType("MyNamespace.MyClass");
+ var method = type?.GetMethod("Run");
+ method?.Invoke(null, null);
}
-}
\ No newline at end of file
+}