diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs index af907c8..eb9487b 100644 --- a/Library/Api/IFlowEnvironment.cs +++ b/Library/Api/IFlowEnvironment.cs @@ -941,6 +941,11 @@ namespace Serein.Library.Api /// IFlowControl FlowControl { get; } + /// + /// 流程依赖类库接口 + /// + IFlowLibraryService FlowLibraryService { get; } + /// /// 流程事件接口 /// @@ -1122,6 +1127,13 @@ namespace Serein.Library.Api /// void ExitRemoteEnv(); */ + + /// + /// 启动远程服务 + /// + /// + Task StartRemoteServerAsync(int port = 7525); + /// /// (用于远程)通知节点属性变更 /// diff --git a/Library/Api/IFlowLibraryService.cs b/Library/Api/IFlowLibraryService.cs new file mode 100644 index 0000000..98562fe --- /dev/null +++ b/Library/Api/IFlowLibraryService.cs @@ -0,0 +1,86 @@ +using Serein.Library; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; + +namespace Serein.Library.Api +{ + /// + /// 流程依赖程序集管理 + /// + public interface IFlowLibraryService + { + /// + /// 是否加载了基础依赖 + /// + bool IsLoadedBaseLibrary { get; } + /// + /// 加载基础依赖 + /// + /// + FlowLibraryInfo LoadBaseLibrary(); + /// + /// 获取已加载的方法信息 + /// + /// + List GetAllLibraryInfo(); + /// + /// 加载指定依赖 + /// + /// + /// + FlowLibraryInfo? LoadFlowLibrary(string libraryfilePath); + /// + /// 卸载程序集 + /// + /// + /// + bool UnloadLibrary(string assemblyName); + /// + /// 获取委托 + /// + /// + /// + /// + /// + bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails dd); + /// + /// 获取方法描述 + /// + /// + /// + /// + /// + bool TryGetMethodDetails(string assemblyName, string methodName, out MethodDetails md); + /// + /// 获取反射方法信息 + /// + /// + /// + /// + /// + bool TryGetMethodInfo(string assemblyName, string methodName, out MethodInfo methodInfo); + /// + /// 获取依赖程序集中的类型 + /// + /// + /// + /// + bool TryGetType(string fullName, out Type? type); + /// + /// 获取依赖程序集中的类型 + /// + /// + /// + Type? GetType(string fullName); + + /// + /// 获取某个节点类型对应的方法描述 + /// + /// + /// + List GetMdsOnFlowStart(NodeType nodeType); + + } +} diff --git a/Library/FlowNode/Env/LightweightFlowEnvironment.cs b/Library/FlowNode/Env/LightweightFlowEnvironment.cs index 9cc3a58..b710b21 100644 --- a/Library/FlowNode/Env/LightweightFlowEnvironment.cs +++ b/Library/FlowNode/Env/LightweightFlowEnvironment.cs @@ -51,6 +51,8 @@ namespace Serein.Library /// public UIContextOperation UIContextOperation => throw new NotImplementedException(); + public IFlowLibraryService FlowLibraryService => throw new NotImplementedException(); + /* public Task<(bool, RemoteMsgUtil)> ConnectRemoteEnv(string addres, int port, string token) { throw new NotImplementedException(); diff --git a/Library/Serein.Library.csproj b/Library/Serein.Library.csproj index 5b49cd5..3c06abf 100644 --- a/Library/Serein.Library.csproj +++ b/Library/Serein.Library.csproj @@ -89,7 +89,8 @@ - + + diff --git a/Library/Utils/UIContextOperation.cs b/Library/Utils/UIContextOperation.cs index f8ce70e..052bde2 100644 --- a/Library/Utils/UIContextOperation.cs +++ b/Library/Utils/UIContextOperation.cs @@ -17,7 +17,7 @@ namespace Serein.Library.Utils public class UIContextOperation { private SynchronizationContext context; - private readonly Func getUiContext = null; + public Func GetUiContext = null; static UIContextOperation() { @@ -55,7 +55,7 @@ namespace Serein.Library.Utils [SereinIOCCtor(IsIgnore = true)] public UIContextOperation(Func getUiContext) { - this.getUiContext = getUiContext; + this.GetUiContext = getUiContext; } /// @@ -65,9 +65,14 @@ namespace Serein.Library.Utils /// 异常发生时的回调 public void Invoke(Action uiAction, Action onException = null) { - if(context is null && getUiContext != null) + + if(context is null && GetUiContext != null) { - context = getUiContext.Invoke(); + while (GetUiContext is null) + { + continue; + } + context = GetUiContext.Invoke(); } context?.Post(state => { @@ -92,9 +97,13 @@ namespace Serein.Library.Utils /// public Task InvokeAsync(Action uiAction, Action onException = null) { - if (context is null && getUiContext != null) + if (context is null ) { - context = getUiContext.Invoke(); + while (GetUiContext is null) + { + continue; + } + context = GetUiContext.Invoke(); } var tcs = new TaskCompletionSource(); diff --git a/NodeFlow/Env/FlowControl.cs b/NodeFlow/Env/FlowControl.cs index 4f561f1..1b9f0dc 100644 --- a/NodeFlow/Env/FlowControl.cs +++ b/NodeFlow/Env/FlowControl.cs @@ -21,25 +21,23 @@ namespace Serein.NodeFlow.Env { private readonly IFlowEnvironment flowEnvironment; private readonly IFlowEnvironmentEvent flowEnvironmentEvent; - private readonly FlowLibraryService flowLibraryService; + private readonly IFlowLibraryService flowLibraryService; private readonly FlowOperationService flowOperationService; private readonly FlowModelService flowModelService; - private readonly UIContextOperation uiContextOperation; + private readonly Lazy uiContextOperation; public FlowControl(IFlowEnvironment flowEnvironment, IFlowEnvironmentEvent flowEnvironmentEvent, - FlowLibraryService flowLibraryService, + IFlowLibraryService flowLibraryService, FlowOperationService flowOperationService, - FlowModelService flowModelService, - UIContextOperation uiContextOperation) + FlowModelService flowModelService) { this.flowEnvironment = flowEnvironment; this.flowEnvironmentEvent = flowEnvironmentEvent; this.flowLibraryService = flowLibraryService; this.flowOperationService = flowOperationService; this.flowModelService = flowModelService; - this.uiContextOperation = uiContextOperation; - + uiContextOperation = new Lazy(() => flowEnvironment.IOC.Get()); contexts = new ObjectPool(() => new FlowContext(flowEnvironment), context => context.Reset()); flowTaskOptions = new FlowWorkOptions { @@ -340,7 +338,7 @@ namespace Serein.NodeFlow.Env { flowWorkManagement.Exit(); } - uiContextOperation?.Invoke(() => flowEnvironmentEvent.OnFlowRunComplete(new FlowEventArgs())); + uiContextOperation.Value.Invoke(() => flowEnvironmentEvent.OnFlowRunComplete(new FlowEventArgs())); IOC.Reset(); GC.Collect(); return Task.FromResult(true); diff --git a/NodeFlow/Env/FlowEdit.cs b/NodeFlow/Env/FlowEdit.cs index 26cad00..169ec37 100644 --- a/NodeFlow/Env/FlowEdit.cs +++ b/NodeFlow/Env/FlowEdit.cs @@ -22,7 +22,7 @@ namespace Serein.NodeFlow.Env { public FlowEdit(IFlowEnvironment flowEnvironment, IFlowEnvironmentEvent flowEnvironmentEvent, - FlowLibraryService flowLibraryManagement, + IFlowLibraryService flowLibraryManagement, FlowOperationService flowOperationService, FlowModelService flowModelService, UIContextOperation UIContextOperation, @@ -45,7 +45,7 @@ namespace Serein.NodeFlow.Env private readonly IFlowEnvironment flowEnvironment; private readonly IFlowEnvironmentEvent flowEnvironmentEvent; - private readonly FlowLibraryService flowLibraryManagement; + private readonly IFlowLibraryService flowLibraryManagement; private readonly FlowOperationService flowOperationService; private readonly FlowModelService flowModelService; diff --git a/NodeFlow/Env/FlowEnvironment.cs b/NodeFlow/Env/FlowEnvironment.cs index 92298ad..5c0dda1 100644 --- a/NodeFlow/Env/FlowEnvironment.cs +++ b/NodeFlow/Env/FlowEnvironment.cs @@ -49,11 +49,46 @@ namespace Serein.NodeFlow.Env public FlowEnvironment() { ISereinIOC ioc = new SereinIOC(); - ioc.Register(()=> ioc) // IOC容器接口 + ioc.Register(() => ioc) // IOC容器接口 .Register(() => this) // 流程环境接口 .Register() // 流程环境事件接口 .Register() // 流程编辑接口 .Register() // 流程控制接口 + .Register() // 流程库服务 + .Register() // 本地环境 + .Register() // 节点/画布模型服务 + .Register() // 代码生成 + .Register() // 流程操作 + .Register() // 节点MVVM服务 + .Build(); + + // 设置JSON解析器 + if (JsonHelper.Provider is null) + { + JsonHelper.UseJsonProvider(new NewtonsoftJsonProvider()); + } + + // 默认使用本地环境 + localFlowEnvironment = ioc.Get(); + currentFlowEnvironmentEvent = ioc.Get(); + currentFlowEnvironment = localFlowEnvironment; + SereinEnv.SetEnv(localFlowEnvironment); + } + + /// + /// 提供上下文操作进行调用 + /// + /// + public FlowEnvironment(UIContextOperation operation) + { + ISereinIOC ioc = new SereinIOC(); + ioc.Register(() => ioc) // IOC容器接口 + .Register(() => this) // 流程环境接口 + .Register() // 流程环境事件接口 + .Register() + .Register(() => operation) // 流程环境接口 + .Register() // 流程编辑接口 + .Register() // 流程控制接口 .Register() // 本地环境 .Register() // 节点/画布模型服务 .Register() // 流程库服务 @@ -67,56 +102,19 @@ namespace Serein.NodeFlow.Env { JsonHelper.UseJsonProvider(new NewtonsoftJsonProvider()); } - + // 默认使用本地环境 - currentFlowEnvironment = ioc.Get(); + localFlowEnvironment = ioc.Get(); currentFlowEnvironmentEvent = ioc.Get(); - SereinEnv.SetEnv(currentFlowEnvironment); + currentFlowEnvironment = localFlowEnvironment; + SereinEnv.SetEnv(localFlowEnvironment); } /// - /// 提供上下文操作进行调用 + /// 管理当前环境 /// - /// - public FlowEnvironment(UIContextOperation operation) - { - ISereinIOC ioc = new SereinIOC(); - ioc.Register(()=> ioc) // IOC容器接口 - .Register(() => operation) // 流程环境接口 - .Register(() => this) // 流程环境接口 - .Register() // 流程环境事件接口 - .Register() // 流程编辑接口 - .Register() // 流程控制接口 - .Register() // 本地环境 - .Register() // 节点/画布模型服务 - .Register() // 流程库服务 - .Register() // 代码生成 - .Register() // 流程操作 - .Register() // 节点MVVM服务 - .Build(); - // 设置JSON解析器 - if (JsonHelper.Provider is null) - { - JsonHelper.UseJsonProvider(new NewtonsoftJsonProvider()); - } - - // 默认使用本地环境 - currentFlowEnvironment = ioc.Get(); - currentFlowEnvironmentEvent = ioc.Get(); - SereinEnv.SetEnv(currentFlowEnvironment); - } -/* - /// - /// 本地环境事件 - /// - private readonly IFlowEnvironmentEvent flowEnvironmentEvent; - - /// - /// 远程环境事件 - /// - private IFlowEnvironmentEvent remoteFlowEnvironmentEvent; - */ + private LocalFlowEnvironment localFlowEnvironment; /// /// 管理当前环境 @@ -129,8 +127,6 @@ namespace Serein.NodeFlow.Env /// private IFlowEnvironmentEvent currentFlowEnvironmentEvent; - - private int _loadingProjectFlag = 0; // 使用原子自增代替锁 /// /// 传入false时,将停止数据通知。传入true时, @@ -159,6 +155,9 @@ namespace Serein.NodeFlow.Env /// public IFlowControl FlowControl => currentFlowEnvironment.FlowControl; + + /// + public IFlowLibraryService FlowLibraryService => currentFlowEnvironment.FlowLibraryService; /// public ISereinIOC IOC => currentFlowEnvironment.IOC; @@ -259,12 +258,6 @@ namespace Serein.NodeFlow.Env SetProjectLoadingFlag(true); } - /* /// - public void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType) - { - currentFlowEnvironment.FlowControl.MonitorObjectNotification(nodeGuid, monitorData, sourceType); - }*/ - /// public bool TryUnloadLibrary(string assemblyName) { @@ -312,43 +305,14 @@ namespace Serein.NodeFlow.Env #endif #endregion -/* /// - public async Task StartFlowAsync(string[] canvasGuids) + public Task StartRemoteServerAsync(int port = 7525) { - return await currentFlowEnvironment.FlowControl.StartFlowAsync(canvasGuids); + + throw new NotImplementedException(); } - /// - public async Task StartFlowAsync(string startNodeGuid) - { - return await currentFlowEnvironment.FlowControl.StartFlowAsync(startNodeGuid); - }*/ - - /* /// - public async Task StartRemoteServerAsync(int port = 7525) - { - await currentFlowEnvironment.StartRemoteServerAsync(port); - } - - /// - public void StopRemoteServer() - { - currentFlowEnvironment.StopRemoteServer(); - }*/ -/* - /// - public void TerminateFlipflopNode(string nodeGuid) - { - currentFlowEnvironment.FlowControl.TerminateFlipflopNode(nodeGuid); - } - - /// - public void TriggerInterrupt(string nodeGuid, string expression, InterruptTriggerEventArgs.InterruptTriggerType type) - { - currentFlowEnvironment.FlowControl.TriggerInterrupt(nodeGuid, expression, type); - }*/ /// public void SetUIContextOperation(UIContextOperation uiContextOperation) @@ -356,12 +320,6 @@ namespace Serein.NodeFlow.Env currentFlowEnvironment.SetUIContextOperation(uiContextOperation); } -/* - /// - public void UseExternalIOC(ISereinIOC ioc) - { - currentFlowEnvironment.FlowControl.UseExternalIOC(ioc); - }*/ /// public bool TryGetNodeModel(string nodeGuid, out IFlowNode nodeModel) @@ -408,6 +366,7 @@ namespace Serein.NodeFlow.Env { currentFlowEnvironment.LoadAllNativeLibraryOfRuning(path,isRecurrence); } + #endregion diff --git a/NodeFlow/Services/FlowCoreGenerateService.cs b/NodeFlow/Services/FlowCoreGenerateService.cs index 8ac62ca..8903b39 100644 --- a/NodeFlow/Services/FlowCoreGenerateService.cs +++ b/NodeFlow/Services/FlowCoreGenerateService.cs @@ -18,14 +18,14 @@ namespace Serein.NodeFlow.Services public class FlowCoreGenerateService { private readonly FlowModelService flowModelService; - private readonly FlowLibraryService flowLibraryService; + private readonly IFlowLibraryService flowLibraryService; /// /// 流程代码生成服务 /// /// /// - public FlowCoreGenerateService(FlowModelService flowModelService ,FlowLibraryService flowLibraryService ) + public FlowCoreGenerateService(FlowModelService flowModelService ,IFlowLibraryService flowLibraryService ) { this.flowModelService = flowModelService; this.flowLibraryService = flowLibraryService; diff --git a/NodeFlow/Services/FlowLibraryService.cs b/NodeFlow/Services/FlowLibraryService.cs index dbc756e..e156672 100644 --- a/NodeFlow/Services/FlowLibraryService.cs +++ b/NodeFlow/Services/FlowLibraryService.cs @@ -9,10 +9,11 @@ using System.Xml.Linq; namespace Serein.NodeFlow.Services { + /// /// 管理加载在运行环境中的外部程序集 /// - public class FlowLibraryService + public class FlowLibraryService : IFlowLibraryService { /// /// 是否加载过基础依赖 @@ -49,7 +50,7 @@ namespace Serein.NodeFlow.Services private bool CheckBaseLibrary(string libraryfilePath, out string baseLibraryPath) { var dir = Path.GetDirectoryName(libraryfilePath); // 获取目录路径 - ArgumentNullException.ThrowIfNullOrWhiteSpace(dir); + ArgumentException.ThrowIfNullOrWhiteSpace(dir); var sereinFlowBaseLibraryPath = Path.Combine(dir, SereinBaseLibrary); if (!Path.Exists(sereinFlowBaseLibraryPath)) { diff --git a/NodeFlow/Services/FlowModelService.cs b/NodeFlow/Services/FlowModelService.cs index 1b82269..feafc5d 100644 --- a/NodeFlow/Services/FlowModelService.cs +++ b/NodeFlow/Services/FlowModelService.cs @@ -7,19 +7,19 @@ using System.Diagnostics.CodeAnalysis; namespace Serein.NodeFlow.Services { /// - /// 流程模型服务 + /// 流程画布/节点数据实体服务 /// public class FlowModelService { private readonly IFlowEnvironment environment; - private readonly FlowLibraryService flowLibraryService; + private readonly IFlowLibraryService flowLibraryService; /// /// 流程模型服务构造函数 /// /// /// - public FlowModelService(IFlowEnvironment environment, FlowLibraryService flowLibraryService) + public FlowModelService(IFlowEnvironment environment, IFlowLibraryService flowLibraryService) { this.environment = environment; this.flowLibraryService = flowLibraryService; diff --git a/NodeFlow/Services/FlowOperationService.cs b/NodeFlow/Services/FlowOperationService.cs index f378a0c..72769dd 100644 --- a/NodeFlow/Services/FlowOperationService.cs +++ b/NodeFlow/Services/FlowOperationService.cs @@ -8,6 +8,9 @@ using System.Threading.Tasks; namespace Serein.NodeFlow.Services { + /// + /// 流程操作 + /// internal class FlowOperationService { private readonly ISereinIOC sereinIOC; diff --git a/Workbench/App.xaml.cs b/Workbench/App.xaml.cs index e3ce229..1bb06aa 100644 --- a/Workbench/App.xaml.cs +++ b/Workbench/App.xaml.cs @@ -65,6 +65,7 @@ namespace Serein.Workbench #endif var projectService = App.GetService(); + if (e.Args.Length == 1) { string filePath = e.Args[0]; diff --git a/Workbench/ServiceCollectionExtensions.cs b/Workbench/ServiceCollectionExtensions.cs index 0436dec..2ae9f5b 100644 --- a/Workbench/ServiceCollectionExtensions.cs +++ b/Workbench/ServiceCollectionExtensions.cs @@ -54,28 +54,48 @@ namespace Serein.Workbench /// public static void AddFlowServices(this IServiceCollection collection) { - #region 创建实例 - JsonHelper.UseJsonProvider(new NewtonsoftJsonProvider()); Func? getSyncContext = null; + UIContextOperation? uIContextOperation = new(getSyncContext); // 封装一个调用UI线程的工具类 + IFlowEnvironment flowEnvironment = new FlowEnvironment(uIContextOperation); Dispatcher.CurrentDispatcher.Invoke(() => { - var uiContext = SynchronizationContext.Current; // 在UI线程上获取UI线程上下文信息 - if (uiContext is not null) + if (SynchronizationContext.Current is { } uiContext) { + // 在UI线程上获取UI线程上下文信息 getSyncContext = () => uiContext; + + flowEnvironment.UIContextOperation.GetUiContext = () => uiContext; } }); - UIContextOperation? uIContextOperation = new (getSyncContext); // 封装一个调用UI线程的工具类 - IFlowEnvironment flowEnvironment = new FlowEnvironment(); - flowEnvironment.SetUIContextOperation(uIContextOperation); - collection.AddSingleton(uIContextOperation); // 注册UI线程操作上下文 collection.AddSingleton(flowEnvironment); // 注册运行环境 collection.AddSingleton(flowEnvironment.Event); // 注册运行环境事件 + collection.AddSingleton(); // 注册工作台环境事件 - #endregion + //#region 创建实例 + + //Func? getSyncContext = null; + //Dispatcher.CurrentDispatcher.Invoke(() => + //{ + // var uiContext = SynchronizationContext.Current; // 在UI线程上获取UI线程上下文信息 + // if (uiContext is not null) + // { + // getSyncContext = () => uiContext; + // } + //}); + //UIContextOperation? uIContextOperation = new (getSyncContext); // 封装一个调用UI线程的工具类 + //IFlowEnvironment flowEnvironment = new FlowEnvironment(); + //flowEnvironment.SetUIContextOperation(uIContextOperation); + + + + //collection.AddSingleton(uIContextOperation); // 注册UI线程操作上下文 + //collection.AddSingleton(flowEnvironment); // 注册运行环境 + //collection.AddSingleton(flowEnvironment.Event); // 注册运行环境事件 + + //#endregion } }