# Conflicts:
#	.idea/.idea.FantasyNetTest/.idea/vcs.xml
This commit is contained in:
bob
2025-08-11 17:20:23 +08:00
2 changed files with 26 additions and 21 deletions

View File

@@ -330,7 +330,7 @@ public partial class Form1 : Form
private void LoadProtocol() private void LoadProtocol()
{ {
Log.Info("开始加载协议"); Log.Info("开始加载协议");
_scriptLoader.LoadAndExecuteScriptsAsync(_config.ProtocolScriptPath); _scriptLoader.LoadAndExecuteScripts(_config.ProtocolScriptPath);
Log.Succeed("加载协议完成"); Log.Succeed("加载协议完成");
CoderLoader.Load(); CoderLoader.Load();
SetProtocolComboBox(); SetProtocolComboBox();

View File

@@ -1,22 +1,26 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.Loader; using System.Runtime.Loader;
using System.Threading.Tasks;
using FantasyNetTest;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
using NBC;
public class ScriptLoader 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); var csFiles = Directory.GetFiles(folderPath, "*.cs", SearchOption.AllDirectories);
if (!csFiles.Any()) if (!csFiles.Any())
@@ -25,20 +29,20 @@ public class ScriptLoader
return; return;
} }
// 2. 创建语法树
var syntaxTrees = csFiles.Select(file => var syntaxTrees = csFiles.Select(file =>
CSharpSyntaxTree.ParseText(File.ReadAllText(file)) CSharpSyntaxTree.ParseText(File.ReadAllText(file))
); );
// 3. 引用程序集
var references = AppDomain.CurrentDomain.GetAssemblies() var references = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => !a.IsDynamic && !string.IsNullOrWhiteSpace(a.Location)) .Where(a => !a.IsDynamic && !string.IsNullOrWhiteSpace(a.Location))
.Select(a => MetadataReference.CreateFromFile(a.Location)) .Select(a => MetadataReference.CreateFromFile(a.Location))
.Cast<MetadataReference>(); .Cast<MetadataReference>();
// 4. 编译成内存程序集 // 每次给程序集一个唯一名字
string asmName = $"DynamicScripts_{Guid.NewGuid():N}";
var compilation = CSharpCompilation.Create( var compilation = CSharpCompilation.Create(
assemblyName: "DynamicScripts", assemblyName: asmName,
syntaxTrees: syntaxTrees, syntaxTrees: syntaxTrees,
references: references, references: references,
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
@@ -54,14 +58,15 @@ public class ScriptLoader
return; return;
} }
// 5. 加载程序集
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
var assembly = AssemblyLoadContext.Default.LoadFromStream(ms); // 用可卸载的 AssemblyLoadContext 加载
var alc = new AssemblyLoadContext(asmName, isCollectible: true);
var assembly = alc.LoadFromStream(ms);
_lastContext = alc;
// 6. 调用示例 var type = assembly.GetType("MyNamespace.MyClass");
var type = assembly.GetType("MyNamespace.MyClass"); // 你的类名 var method = type?.GetMethod("Run");
var method = type?.GetMethod("Run"); // 你的方法名 method?.Invoke(null, null);
method?.Invoke(null, null); // 假设是静态方法无参数
} }
} }