diff --git a/src/modules/scripting/Application/Services/ScriptTypeRegistry.cs b/src/modules/scripting/Application/Services/ScriptTypeRegistry.cs index 4f84795..69575e0 100644 --- a/src/modules/scripting/Application/Services/ScriptTypeRegistry.cs +++ b/src/modules/scripting/Application/Services/ScriptTypeRegistry.cs @@ -14,6 +14,16 @@ public class ScriptTypeRegistry { private readonly ConcurrentDictionary _types = new(); + /// + /// 业务模块程序集前缀白名单。脚本编辑器应能调用的 CQRS 入口集中在各业务模块的 Application 层; + /// 命名约定为 <Module>.Application/Domain/Infrastructure,模块根名如下。 + /// 注意:rag 模块与共享层使用 BuildFlow. 前缀,故 BuildFlow 也纳入。 + /// + private static readonly string[] _modulePrefixes = + { + "Platform", "Workflow", "Scripting", "File", "IM", "Rag", "BuildFlow" + }; + /// 执行(或刷新)扫描。幂等:重复调用会重建字典。 public void Scan() { @@ -21,11 +31,7 @@ public class ScriptTypeRegistry foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) { var name = asm.GetName().Name ?? string.Empty; - if (!name.StartsWith("BuildFlow", StringComparison.Ordinal)) continue; - // 排除测试与基础设施程序集:脚本沙箱内无法引用这些类型,列出它们只会误导用户 - if (name.EndsWith(".Tests", StringComparison.Ordinal)) continue; - if (name.EndsWith(".Test", StringComparison.Ordinal)) continue; - if (name.EndsWith(".Infrastructure", StringComparison.Ordinal)) continue; + if (!IsBusinessModuleAssembly(name)) continue; Type[] types; try { types = asm.GetTypes(); } @@ -47,6 +53,27 @@ public class ScriptTypeRegistry foreach (var m in found) _types[m.FullName] = m; } + /// + /// 判定程序集是否属于业务模块(而非框架/测试/宿主/基础设施)。 + /// 脚本沙箱内无法引用 Infrastructure 类型,故一并排除,避免方法面板列出不可达类型。 + /// + private static bool IsBusinessModuleAssembly(string name) + { + if (string.IsNullOrEmpty(name)) return false; + // 排除测试与基础设施程序集 + if (name.EndsWith(".Tests", StringComparison.Ordinal)) return false; + if (name.EndsWith(".Test", StringComparison.Ordinal)) return false; + if (name.EndsWith(".Infrastructure", StringComparison.Ordinal)) return false; + // 宿主程序集本身不含可调用的 request 类型,且脚本不应耦合端点层 + if (name.EndsWith(".Host", StringComparison.Ordinal)) return false; + // 必须匹配某个业务模块前缀("Prefix." 或恰好等于 "Prefix") + foreach (var p in _modulePrefixes) + { + if (name == p || name.StartsWith(p + ".", StringComparison.Ordinal)) return true; + } + return false; + } + private static ScriptTypeMeta BuildMeta(Type type) { var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)