From 87402ec7ea958c9e7d374a0ee31b672ad7e0e39c Mon Sep 17 00:00:00 2001 From: fengjiayi <12821976+ning_xi@user.noreply.gitee.com> Date: Tue, 18 Mar 2025 12:33:54 +0800 Subject: [PATCH] =?UTF-8?q?NodeMVVMManagement=E4=B8=8D=E5=86=8D=E6=98=AF?= =?UTF-8?q?=E9=9D=99=E6=80=81=E7=B1=BB=EF=BC=8C=E8=80=8C=E6=98=AF=E8=BF=90?= =?UTF-8?q?=E8=A1=8C=E7=8E=AF=E5=A2=83=E5=86=85=E9=83=A8=E7=9A=84=E6=88=90?= =?UTF-8?q?=E5=91=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/Api/IFlowEnvironment.cs | 5 +- Library/FlowNode/ContainerFlowEnvironment.cs | 1 + .../FlowNode}/NodeMVVMManagement.cs | 22 +++--- Library/Serein.Library.csproj | 3 +- NodeFlow/Env/FlowEnvironment.cs | 13 ++- NodeFlow/Env/FlowEnvironmentDecorator.cs | 4 + NodeFlow/Env/RemoteFlowEnvironment.cs | 1 + NodeFlow/FlowFunc.cs | 2 +- NodeFlow/Tool/DynamicCompiler.cs | 4 +- NodeFlow/Tool/FlowLibrary.cs | 14 ++-- NodeFlow/Tool/FlowLibraryManagement.cs | 79 +++++++++++-------- Workbench/MainWindow.xaml.cs | 24 +++--- .../NetScriptNodeControlViewModel.cs | 3 +- Workbench/Themes/DynamicCompilerView.xaml.cs | 12 +-- 14 files changed, 110 insertions(+), 77 deletions(-) rename {NodeFlow => Library/FlowNode}/NodeMVVMManagement.cs (80%) diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs index 6dfa618..8b491bd 100644 --- a/Library/Api/IFlowEnvironment.cs +++ b/Library/Api/IFlowEnvironment.cs @@ -705,7 +705,10 @@ namespace Serein.Library.Api /// UIContextOperation UIContextOperation { get; } - + /// + /// 节点视图模型管理类 + /// + NodeMVVMManagement NodeMVVMManagement { get; } #endregion #region 基本接口 diff --git a/Library/FlowNode/ContainerFlowEnvironment.cs b/Library/FlowNode/ContainerFlowEnvironment.cs index 400aaf7..97b6aff 100644 --- a/Library/FlowNode/ContainerFlowEnvironment.cs +++ b/Library/FlowNode/ContainerFlowEnvironment.cs @@ -40,6 +40,7 @@ namespace Serein.Library public IFlowEnvironment CurrentEnv => this; public UIContextOperation UIContextOperation { get; set; } + public NodeMVVMManagement NodeMVVMManagement { get; set; } /// /// 设置在UI线程操作的线程上下文 diff --git a/NodeFlow/NodeMVVMManagement.cs b/Library/FlowNode/NodeMVVMManagement.cs similarity index 80% rename from NodeFlow/NodeMVVMManagement.cs rename to Library/FlowNode/NodeMVVMManagement.cs index a5a327a..ee7def3 100644 --- a/NodeFlow/NodeMVVMManagement.cs +++ b/Library/FlowNode/NodeMVVMManagement.cs @@ -7,32 +7,34 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace Serein.NodeFlow +namespace Serein.Library { /// /// 节点类型 /// public class NodeMVVM { + + /// /// 节点类型 /// - public required NodeControlType NodeType { get; set; } + public NodeControlType NodeType { get; set; } /// /// 节点Model类型 /// - public required Type ModelType { get; set; } + public Type ModelType { get; set; } /// /// 节点视图控件类型 /// - public Type? ControlType { get; set; } + public Type ControlType { get; set; } /// /// 节点视图VM类型 /// - public Type? ViewModelType { get; set; } + public Type ViewModelType { get; set; } public override string ToString() { @@ -43,19 +45,19 @@ namespace Serein.NodeFlow /// /// 节点 数据、视图、VM 管理 /// - public static class NodeMVVMManagement + public class NodeMVVMManagement { /// /// 节点对应的控件类型 /// - private static ConcurrentDictionary FlowNodeTypes { get; } = []; + private ConcurrentDictionary FlowNodeTypes { get; } = []; /// /// 注册 Model 类型 /// /// /// - public static bool RegisterModel(NodeControlType type, Type modelType) + public bool RegisterModel(NodeControlType type, Type modelType) { if(FlowNodeTypes.TryGetValue(type,out var nodeMVVM)) { @@ -76,7 +78,7 @@ namespace Serein.NodeFlow /// /// /// - public static bool RegisterUI(NodeControlType type, Type controlType,Type viewModelType) + public bool RegisterUI(NodeControlType type, Type controlType,Type viewModelType) { if (!FlowNodeTypes.TryGetValue(type, out var nodeMVVM)) { @@ -94,7 +96,7 @@ namespace Serein.NodeFlow /// /// /// - public static bool TryGetType(NodeControlType type, out NodeMVVM nodeMVVM) + public bool TryGetType(NodeControlType type, out NodeMVVM nodeMVVM) { if( FlowNodeTypes.TryGetValue(type, out nodeMVVM)) { diff --git a/Library/Serein.Library.csproj b/Library/Serein.Library.csproj index 32f6161..e81bb66 100644 --- a/Library/Serein.Library.csproj +++ b/Library/Serein.Library.csproj @@ -12,7 +12,8 @@ https://github.com/fhhyyp/serein-flow MIT True - + latest + true true .\obj\g diff --git a/NodeFlow/Env/FlowEnvironment.cs b/NodeFlow/Env/FlowEnvironment.cs index 35c6de0..0b07d23 100644 --- a/NodeFlow/Env/FlowEnvironment.cs +++ b/NodeFlow/Env/FlowEnvironment.cs @@ -42,7 +42,7 @@ namespace Serein.NodeFlow.Env }; this.FlowLibraryManagement = new FlowLibraryManagement(this); // 实例化类库管理 - + this.NodeMVVMManagement = new NodeMVVMManagement(); #region 注册基本节点类型 NodeMVVMManagement.RegisterModel(NodeControlType.UI, typeof(SingleUINode)); // 动作节点 @@ -214,6 +214,11 @@ namespace Serein.NodeFlow.Env /// public UIContextOperation UIContextOperation { get; set; } + /// + /// 节点视图模型管理类 + /// + public NodeMVVMManagement NodeMVVMManagement { get; set; } + /// /// 信息输出等级 /// @@ -654,12 +659,12 @@ namespace Serein.NodeFlow.Env /// /// 加载本地程序集 /// - /// - public void LoadLibrary(Assembly assembly) + /// + public void LoadLibrary(FlowLibrary flowLibrary) { try { - (var libraryInfo, var mdInfos) = FlowLibraryManagement.LoadLibraryOfPath(assembly); + (var libraryInfo, var mdInfos) = FlowLibraryManagement.LoadLibraryOfPath(flowLibrary); if (mdInfos.Count > 0) { UIContextOperation?.Invoke(() => OnDllLoad?.Invoke(new LoadDllEventArgs(libraryInfo, mdInfos))); // 通知UI创建dll面板显示 diff --git a/NodeFlow/Env/FlowEnvironmentDecorator.cs b/NodeFlow/Env/FlowEnvironmentDecorator.cs index 2597bd1..6fffc02 100644 --- a/NodeFlow/Env/FlowEnvironmentDecorator.cs +++ b/NodeFlow/Env/FlowEnvironmentDecorator.cs @@ -82,6 +82,10 @@ namespace Serein.NodeFlow.Env public IFlowEnvironment CurrentEnv { get => currentFlowEnvironment; } public UIContextOperation UIContextOperation => currentFlowEnvironment.UIContextOperation; + /// + /// 节点视图模型管理类 + /// + public NodeMVVMManagement NodeMVVMManagement => currentFlowEnvironment.NodeMVVMManagement; public ISereinIOC IOC => (ISereinIOC)currentFlowEnvironment; diff --git a/NodeFlow/Env/RemoteFlowEnvironment.cs b/NodeFlow/Env/RemoteFlowEnvironment.cs index f4a2f48..ebadaf1 100644 --- a/NodeFlow/Env/RemoteFlowEnvironment.cs +++ b/NodeFlow/Env/RemoteFlowEnvironment.cs @@ -83,6 +83,7 @@ namespace Serein.NodeFlow.Env public IFlowEnvironment CurrentEnv => this; public UIContextOperation UIContextOperation { get; } + public NodeMVVMManagement NodeMVVMManagement { get; } /// /// 标示是否正在加载项目 diff --git a/NodeFlow/FlowFunc.cs b/NodeFlow/FlowFunc.cs index 5c39c7f..2609bca 100644 --- a/NodeFlow/FlowFunc.cs +++ b/NodeFlow/FlowFunc.cs @@ -43,7 +43,7 @@ namespace Serein.NodeFlow // 尝试获取需要创建的节点类型 - if (!NodeMVVMManagement.TryGetType(nodeControlType, out var nodeMVVM) || nodeMVVM.ModelType == null) + if (!env.NodeMVVMManagement.TryGetType(nodeControlType, out var nodeMVVM) || nodeMVVM.ModelType == null) { throw new Exception($"无法创建{nodeControlType}节点,节点类型尚未注册。"); } diff --git a/NodeFlow/Tool/DynamicCompiler.cs b/NodeFlow/Tool/DynamicCompiler.cs index 7b563e9..9d3d7fc 100644 --- a/NodeFlow/Tool/DynamicCompiler.cs +++ b/NodeFlow/Tool/DynamicCompiler.cs @@ -101,13 +101,13 @@ namespace Serein.NodeFlow.Tool } return null; } + ms.Seek(0, SeekOrigin.Begin); + var t12 = AppContext.BaseDirectory; var assembly = Assembly.Load(ms.ToArray()); var t1 = assembly.Location; var t = assembly.GetType().Assembly.Location; - - // 保存 compilation.Emit(savePath); diff --git a/NodeFlow/Tool/FlowLibrary.cs b/NodeFlow/Tool/FlowLibrary.cs index 56923af..eff5b15 100644 --- a/NodeFlow/Tool/FlowLibrary.cs +++ b/NodeFlow/Tool/FlowLibrary.cs @@ -26,7 +26,7 @@ namespace Serein.NodeFlow /// public class FlowLibrary { - private readonly Assembly _assembly; + public Assembly Assembly { get; private set; } @@ -36,16 +36,16 @@ namespace Serein.NodeFlow public FlowLibrary(Assembly assembly) { - this._assembly = assembly; - this.FullName = Path.GetFileName(_assembly.Location); + this.Assembly = assembly; + this.FullName = Path.GetFileName(Assembly.Location); - this.FilePath = _assembly.Location; + this.FilePath = Assembly.Location; } public FlowLibrary(Assembly assembly, string filePath) { - this._assembly = assembly; + this.Assembly = assembly; this.FullName = Path.GetFileName(filePath); ; this.FilePath = filePath; } @@ -92,7 +92,7 @@ namespace Serein.NodeFlow /// public NodeLibraryInfo ToInfo() { - var assemblyName = _assembly.GetName().Name; + var assemblyName = Assembly.GetName().Name; return new NodeLibraryInfo { AssemblyName = assemblyName, @@ -111,7 +111,7 @@ namespace Serein.NodeFlow /// public bool LoadAssembly() { - Assembly assembly = this._assembly; + Assembly assembly = this.Assembly; #region 检查入参 // 加载DLL,创建 MethodDetails、实例作用对象、委托方法 diff --git a/NodeFlow/Tool/FlowLibraryManagement.cs b/NodeFlow/Tool/FlowLibraryManagement.cs index e06f953..8ec72bd 100644 --- a/NodeFlow/Tool/FlowLibraryManagement.cs +++ b/NodeFlow/Tool/FlowLibraryManagement.cs @@ -49,26 +49,31 @@ namespace Serein.NodeFlow.Tool var flowAlc = new FlowLibraryAssemblyContext(sereinFlowBaseLibraryPath, Path.GetFileName(libraryfilePath)); var assembly = flowAlc.LoadFromAssemblyPath(libraryfilePath); // 加载指定路径的程序集 - var reulst = LoadDllNodeInfo(assembly); - if(reulst.Item1 is null || reulst.Item2.Count == 0) + + var flowLibrary = new FlowLibrary(assembly); + try + { + var reulst = LoadFlowLibrary(flowLibrary); + return reulst; + } + catch (Exception) { flowAlc?.Unload(); // 卸载程序集 flowAlc = null; GC.Collect(); // 强制触发GC确保卸载成功 GC.WaitForPendingFinalizers(); - throw new Exception("从文件加载DLL失败:"+ libraryfilePath); + throw; } - return reulst; } /// /// 加载类库 /// - /// + /// /// - public (NodeLibraryInfo, List) LoadLibraryOfPath(Assembly assembly) + public (NodeLibraryInfo, List) LoadLibraryOfPath(FlowLibrary flowLibrary) { - return LoadDllNodeInfo(assembly); + return LoadFlowLibrary(flowLibrary); } /// @@ -235,38 +240,48 @@ namespace Serein.NodeFlow.Tool /// public readonly static string SereinBaseLibrary = $"{nameof(Serein)}.{nameof(Serein.Library)}.dll"; - private (NodeLibraryInfo, List) LoadDllNodeInfo(Assembly assembly) - { + //private (NodeLibraryInfo, List) LoadDllNodeInfo(Assembly assembly) + //{ + // if (assembly.FullName?.ToString().Equals(typeof(IFlowEnvironment).Assembly.FullName?.ToString()) == true) + // { + + // // 加载基础依赖 + // return LoadAssembly(typeof(IFlowEnvironment).Assembly); + // } + // else + // { + // try + // { + // var assembly_result = LoadAssembly(assembly); + // return assembly_result; + // } + // catch (Exception) + // { + // return (null,[]); + // } + + // } + + //} + + + + private (NodeLibraryInfo, List) LoadFlowLibrary(FlowLibrary flowLibrary) + { + var assembly = flowLibrary.Assembly; if (assembly.FullName?.ToString().Equals(typeof(IFlowEnvironment).Assembly.FullName?.ToString()) == true) { // 加载基础依赖 - return LoadAssembly(typeof(IFlowEnvironment).Assembly); - } - else - { - try - { - var assembly_result = LoadAssembly(assembly); - return assembly_result; - } - catch (Exception) - { - return (null,[]); - } - + flowLibrary = new FlowLibrary(typeof(IFlowEnvironment).Assembly); } - } + var assmblyName = assembly.GetName().Name; + if (!string.IsNullOrEmpty(assmblyName) && _myFlowLibrarys.ContainsKey(assmblyName)) + { + throw new Exception($"程序集[{assembly.GetName().FullName}]已经加载过!"); + } - private (NodeLibraryInfo, List) LoadAssembly(Assembly assembly) - { - if (_myFlowLibrarys.ContainsKey(assembly.GetName().Name)) - { - throw new Exception($"程序集[{assembly.GetName().FullName}]已经加载过!"); - } - - FlowLibrary flowLibrary = new FlowLibrary(assembly); var loadResult = flowLibrary.LoadAssembly(); // 加载程序集 if (loadResult) { diff --git a/Workbench/MainWindow.xaml.cs b/Workbench/MainWindow.xaml.cs index 58e0d71..12101fd 100644 --- a/Workbench/MainWindow.xaml.cs +++ b/Workbench/MainWindow.xaml.cs @@ -164,15 +164,15 @@ namespace Serein.Workbench IOCObjectViewer.SelectObj += ViewObjectViewer.LoadObjectInformation; // 使选择 IOC容器视图 的某项(对象)时,可以在 数据视图 呈现数据 #region 为 NodeControlType 枚举 不同项添加对应的 Control类型 、 ViewModel类型 - NodeMVVMManagement.RegisterUI(NodeControlType.UI, typeof(UINodeControl), typeof(UINodeControlViewModel)); - NodeMVVMManagement.RegisterUI(NodeControlType.Action, typeof(ActionNodeControl), typeof(ActionNodeControlViewModel)); - NodeMVVMManagement.RegisterUI(NodeControlType.Flipflop, typeof(FlipflopNodeControl), typeof(FlipflopNodeControlViewModel)); - NodeMVVMManagement.RegisterUI(NodeControlType.ExpOp, typeof(ExpOpNodeControl), typeof(ExpOpNodeControlViewModel)); - NodeMVVMManagement.RegisterUI(NodeControlType.ExpCondition, typeof(ConditionNodeControl), typeof(ConditionNodeControlViewModel)); - NodeMVVMManagement.RegisterUI(NodeControlType.ConditionRegion, typeof(ConditionRegionControl), typeof(ConditionRegionNodeControlViewModel)); - NodeMVVMManagement.RegisterUI(NodeControlType.GlobalData, typeof(GlobalDataControl), typeof(GlobalDataNodeControlViewModel)); - NodeMVVMManagement.RegisterUI(NodeControlType.Script, typeof(ScriptNodeControl), typeof(ScriptNodeControlViewModel)); - NodeMVVMManagement.RegisterUI(NodeControlType.NetScript, typeof(NetScriptNodeControl), typeof(NetScriptNodeControlViewModel)); + EnvDecorator.NodeMVVMManagement.RegisterUI(NodeControlType.UI, typeof(UINodeControl), typeof(UINodeControlViewModel)); + EnvDecorator.NodeMVVMManagement.RegisterUI(NodeControlType.Action, typeof(ActionNodeControl), typeof(ActionNodeControlViewModel)); + EnvDecorator.NodeMVVMManagement.RegisterUI(NodeControlType.Flipflop, typeof(FlipflopNodeControl), typeof(FlipflopNodeControlViewModel)); + EnvDecorator.NodeMVVMManagement.RegisterUI(NodeControlType.ExpOp, typeof(ExpOpNodeControl), typeof(ExpOpNodeControlViewModel)); + EnvDecorator.NodeMVVMManagement.RegisterUI(NodeControlType.ExpCondition, typeof(ConditionNodeControl), typeof(ConditionNodeControlViewModel)); + EnvDecorator.NodeMVVMManagement.RegisterUI(NodeControlType.ConditionRegion, typeof(ConditionRegionControl), typeof(ConditionRegionNodeControlViewModel)); + EnvDecorator.NodeMVVMManagement.RegisterUI(NodeControlType.GlobalData, typeof(GlobalDataControl), typeof(GlobalDataNodeControlViewModel)); + EnvDecorator.NodeMVVMManagement.RegisterUI(NodeControlType.Script, typeof(ScriptNodeControl), typeof(ScriptNodeControlViewModel)); + EnvDecorator.NodeMVVMManagement.RegisterUI(NodeControlType.NetScript, typeof(NetScriptNodeControl), typeof(NetScriptNodeControlViewModel)); #endregion @@ -733,7 +733,7 @@ namespace Serein.Workbench PositionOfUI position = eventArgs.Position; - if(!NodeMVVMManagement.TryGetType(nodeModel.ControlType, out var nodeMVVM)) + if(!EnvDecorator.NodeMVVMManagement.TryGetType(nodeModel.ControlType, out var nodeMVVM)) { SereinEnv.WriteLine(InfoType.INFO, $"无法创建{nodeModel.ControlType}节点,节点类型尚未注册。"); return; @@ -2707,11 +2707,11 @@ public class FlowLibrary DynamicCompilerView dynamicCompilerView = new DynamicCompilerView(); dynamicCompilerView.ScriptCode = script; - dynamicCompilerView.OnCompileComplete = (assembly) => + dynamicCompilerView.OnCompileComplete = (flowLibrary) => { if(EnvDecorator.CurrentEnv is FlowEnvironment environment) { - environment.LoadLibrary(assembly); + environment.LoadLibrary(flowLibrary); } //EnvDecorator.LoadLibrary }; diff --git a/Workbench/Node/ViewModel/NetScriptNodeControlViewModel.cs b/Workbench/Node/ViewModel/NetScriptNodeControlViewModel.cs index 5e090ef..e9c8dcb 100644 --- a/Workbench/Node/ViewModel/NetScriptNodeControlViewModel.cs +++ b/Workbench/Node/ViewModel/NetScriptNodeControlViewModel.cs @@ -71,9 +71,8 @@ public class FlowLibrary }); } - private static void OnCompileComplete(System.Reflection.Assembly assembly) + private static void OnCompileComplete(FlowLibrary flowLibrary) { - FlowLibrary flowLibrary = new FlowLibrary(assembly); var loadResult = flowLibrary.LoadAssembly(); // 动态编译完成后加载程序集 if (!loadResult) { diff --git a/Workbench/Themes/DynamicCompilerView.xaml.cs b/Workbench/Themes/DynamicCompilerView.xaml.cs index b205346..4e0d108 100644 --- a/Workbench/Themes/DynamicCompilerView.xaml.cs +++ b/Workbench/Themes/DynamicCompilerView.xaml.cs @@ -1,4 +1,5 @@ using Microsoft.Win32; +using Serein.NodeFlow; using Serein.NodeFlow.Tool; using System; using System.Collections.Generic; @@ -33,7 +34,7 @@ namespace Serein.Workbench.Themes /// /// 编译成功回调 /// - public Action OnCompileComplete { get; set; } + public Action OnCompileComplete { get; set; } public DynamicCompilerView() { InitializeComponent(); @@ -127,16 +128,17 @@ namespace Serein.Workbench.Themes try { txtErrors.Clear(); - string code = codeEditor.Text; - Assembly assembly = _compiler.Compile(code, textboxAssemblyName.Text); - + var code = codeEditor.Text; + var path = textboxAssemblyName.Text; + Assembly assembly = _compiler.Compile(code, path); + FlowLibrary flowLibrary = new FlowLibrary(assembly, path); if (assembly != null) { txtErrors.Text = "编译成功!"; txtErrors.Background = System.Windows.Media.Brushes.LightGreen; - OnCompileComplete.Invoke(assembly); + OnCompileComplete.Invoke(flowLibrary); count++; } }