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()
|
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();
|
||||||
|
|||||||
@@ -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); // 假设是静态方法无参数
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user