Merge branch 'master' of https://git.bobsong.cn/Game/FantasyNetTest
# Conflicts: # .idea/.idea.FantasyNetTest/.idea/vcs.xml
This commit is contained in:
@@ -330,7 +330,7 @@ public partial class Form1 : Form
|
||||
private void LoadProtocol()
|
||||
{
|
||||
Log.Info("开始加载协议");
|
||||
_scriptLoader.LoadAndExecuteScriptsAsync(_config.ProtocolScriptPath);
|
||||
_scriptLoader.LoadAndExecuteScripts(_config.ProtocolScriptPath);
|
||||
Log.Succeed("加载协议完成");
|
||||
CoderLoader.Load();
|
||||
SetProtocolComboBox();
|
||||
|
||||
@@ -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<MetadataReference>();
|
||||
|
||||
// 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);
|
||||
// 用可卸载的 AssemblyLoadContext 加载
|
||||
var alc = new AssemblyLoadContext(asmName, isCollectible: true);
|
||||
var assembly = alc.LoadFromStream(ms);
|
||||
_lastContext = alc;
|
||||
|
||||
// 6. 调用示例
|
||||
var type = assembly.GetType("MyNamespace.MyClass"); // 你的类名
|
||||
var method = type?.GetMethod("Run"); // 你的方法名
|
||||
method?.Invoke(null, null); // 假设是静态方法无参数
|
||||
var type = assembly.GetType("MyNamespace.MyClass");
|
||||
var method = type?.GetMethod("Run");
|
||||
method?.Invoke(null, null);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user