diff --git a/Library/Utils/EmitHelper.cs b/Library/Utils/EmitHelper.cs index 30baed3..6510ede 100644 --- a/Library/Utils/EmitHelper.cs +++ b/Library/Utils/EmitHelper.cs @@ -64,6 +64,11 @@ namespace Serein.Library.Utils TaskHasResult, } + static Task ConvertTaskResult(Task task) where T : class + { + return task.ContinueWith(t => (object)t.Result); + } + /// /// 判断一个类型是否为泛型 Task<T> 或 Task,并返回泛型参数类型(如果有的话) /// @@ -100,11 +105,6 @@ namespace Serein.Library.Utils /// /// /// - /// - /// 根据方法信息创建动态调用的委托,返回方法类型,以及传出一个委托 - /// - /// - /// /// public static EmitMethodInfo CreateMethod(MethodInfo methodInfo, out Delegate @delegate) { @@ -205,6 +205,17 @@ namespace Serein.Library.Utils // ============================== il.Emit(isStatic ? OpCodes.Call : OpCodes.Callvirt, methodInfo); + // 如果是泛型Task + if (isTaskGeneric && taskResultType is not null) + { + var convertMethod = typeof(EmitHelper) + .GetMethod(nameof(ConvertTaskResult), + BindingFlags.Static | BindingFlags.NonPublic)! + .MakeGenericMethod(taskResultType); + + il.Emit(OpCodes.Call, convertMethod); + } + // ============================== // 6. 回写 ref / out 参数 // ============================== @@ -237,6 +248,8 @@ namespace Serein.Library.Utils il.Emit(OpCodes.Box, methodInfo.ReturnType); } + + il.Emit(OpCodes.Ret); // ============================== diff --git a/Library/Utils/SereinEnv.cs b/Library/Utils/SereinEnv.cs index 00da5c5..dac9b9d 100644 --- a/Library/Utils/SereinEnv.cs +++ b/Library/Utils/SereinEnv.cs @@ -17,7 +17,10 @@ namespace Serein.Library /// public static class SereinEnv { - private static IFlowEnvironment environment; + /// + /// 运行环境 + /// + public static IFlowEnvironment Environment { get;private set; } #region 全局数据(暂时使用静态全局变量) /// @@ -112,7 +115,7 @@ namespace Serein.Library { if (environment != null) { - SereinEnv.environment = environment; + SereinEnv.Environment = environment; } } @@ -126,7 +129,7 @@ namespace Serein.Library { Debug.WriteLine($"{type} : {message}"); Console.WriteLine($"{type} : {message}"); - SereinEnv.environment?.WriteLine(type,message,@class); + SereinEnv.Environment?.WriteLine(type,message,@class); } /// @@ -139,12 +142,12 @@ namespace Serein.Library if(@class == InfoClass.Debug) { - SereinEnv.environment.WriteLine(InfoType.ERROR, ex.ToString(), @class); + SereinEnv.Environment.WriteLine(InfoType.ERROR, ex.ToString(), @class); } else { - SereinEnv.environment.WriteLine(InfoType.ERROR, ex.Message, @class); + SereinEnv.Environment.WriteLine(InfoType.ERROR, ex.Message, @class); } } @@ -157,13 +160,13 @@ namespace Serein.Library /// public async static Task TriggerEvent(Action action) { - if (environment is null) + if (Environment is null) { action?.Invoke(); } else { - var uco = environment.UIContextOperation; + var uco = Environment.UIContextOperation; if (uco is null) { action?.Invoke(); diff --git a/Library/Utils/SereinIoc.cs b/Library/Utils/SereinIoc.cs index a663a0e..9698af6 100644 --- a/Library/Utils/SereinIoc.cs +++ b/Library/Utils/SereinIoc.cs @@ -510,13 +510,15 @@ namespace Serein.Library.Utils { return null; } - else { // 没有显示指定构造函数入参,选择参数最多的构造函数 //var constructor = GetConstructorWithMostParameters(type); var constructors = GetConstructor(type); // 获取构造函数 - + if(constructors.Length == 0) + { + return null; + } foreach(var constructor in constructors) { var parameters = constructor.GetParameters(); @@ -534,8 +536,10 @@ namespace Serein.Library.Utils argObj = CreateInstance(fullName); if (argObj is null) { - SereinEnv.WriteLine(InfoType.WARN, "构造参数创建失败"); - continue; + SereinEnv.WriteLine(InfoType.WARN, "构造参数创建失败"); + + argObj = CreateInstance(fullName); + throw new Exception("构造参数创建失败"); } } args[i] = argObj; @@ -545,7 +549,7 @@ namespace Serein.Library.Utils instance = Activator.CreateInstance(type, args); if(instance != null) { - break; + break; // 构建完成退出 } } catch (Exception) @@ -553,10 +557,7 @@ namespace Serein.Library.Utils continue; } } - - } - InjectDependencies(instance); // 完成创建后注入实例需要的特性依赖项 _dependencies[typeName] = instance; return instance; @@ -662,7 +663,7 @@ namespace Serein.Library.Utils /// /// 实例 /// 未完成依赖项注入时是否记录 - private bool InjectDependencies(object instance,bool isRecord = true) + private bool InjectDependencies(object instance, bool isRecord = true) { var properties = instance.GetType() .GetProperties(BindingFlags.Instance | BindingFlags.Public).ToArray() diff --git a/NodeFlow/Env/LocalFlowEnvironment.cs b/NodeFlow/Env/LocalFlowEnvironment.cs index 00076b9..3e36e37 100644 --- a/NodeFlow/Env/LocalFlowEnvironment.cs +++ b/NodeFlow/Env/LocalFlowEnvironment.cs @@ -29,9 +29,10 @@ namespace Serein.NodeFlow.Env /// public LocalFlowEnvironment(IFlowEnvironment flowEnvironment, IFlowEnvironmentEvent flowEnvironmentEvent, - FlowLibraryService flowLibraryManagement, + IFlowLibraryService flowLibraryManagement, FlowOperationService flowOperationService, FlowModelService flowModelService, + UIContextOperation uIContextOperation, IFlowControl flowControl, IFlowEdit flowEdit, ISereinIOC sereinIOC, @@ -42,7 +43,8 @@ namespace Serein.NodeFlow.Env FlowEdit = flowEdit; IOC = sereinIOC; FlowControl = flowControl; - _flowLibraryService = flowLibraryManagement; + FlowLibraryService = flowLibraryManagement; + UIContextOperation = uIContextOperation; _flowModelService = flowModelService; _flowOperationService = flowOperationService; _IsGlobalInterrupt = false; @@ -114,6 +116,11 @@ namespace Serein.NodeFlow.Env /// public IFlowControl FlowControl { get; set; } + /// + /// 通过程序集名称管理动态加载的程序集,用于节点创建提供方法描述,流程运行时提供Emit委托 + /// + public IFlowLibraryService FlowLibraryService { get; set; } + /// /// UI线程操作类 /// @@ -184,10 +191,7 @@ namespace Serein.NodeFlow.Env /// private ISereinIOC _flowEnvIOC; - /// - /// 通过程序集名称管理动态加载的程序集,用于节点创建提供方法描述,流程运行时提供Emit委托 - /// - private readonly FlowLibraryService _flowLibraryService; + /// /// 流程节点操作服务 @@ -302,9 +306,9 @@ namespace Serein.NodeFlow.Env } var projectData = flowProjectData ?? throw new ArgumentNullException(nameof(flowProjectData)); - if (!_flowLibraryService.IsLoadedBaseLibrary) + if (!FlowLibraryService.IsLoadedBaseLibrary) { - var baseLibrary = _flowLibraryService.LoadBaseLibrary(); + var baseLibrary = FlowLibraryService.LoadBaseLibrary(); if (baseLibrary.MethodInfos.Count > 0 && UIContextOperation is not null) { await UIContextOperation.InvokeAsync(() => Event.OnDllLoad(new LoadDllEventArgs(baseLibrary))); // 通知UI创建dll面板显示 @@ -360,7 +364,7 @@ namespace Serein.NodeFlow.Env { var projectData = new SereinProjectData() { - Librarys = this._flowLibraryService.GetAllLibraryInfo().ToArray(), + Librarys = this.FlowLibraryService.GetAllLibraryInfo().ToArray(), Nodes = _flowModelService.GetAllNodeModel() .Select(node => node.ToInfo()) .Where(info => info is not null) @@ -384,7 +388,8 @@ namespace Serein.NodeFlow.Env { try { - var libraryInfo = _flowLibraryService.LoadFlowLibrary(dllPath); + + var libraryInfo = FlowLibraryService.LoadFlowLibrary(dllPath); if (libraryInfo is not null && libraryInfo.MethodInfos.Count > 0) { UIContextOperation?.Invoke(() => Event.OnDllLoad(new LoadDllEventArgs(libraryInfo))); // 通知UI创建dll面板显示 @@ -407,7 +412,7 @@ namespace Serein.NodeFlow.Env var groupedNodes = _flowModelService.GetAllNodeModel().Where(node => !string.IsNullOrWhiteSpace(node.MethodDetails.AssemblyName) && node.MethodDetails.AssemblyName.Equals(assemblyName)).ToArray(); if (groupedNodes.Length == 0) { - var isPass = _flowLibraryService.UnloadLibrary(assemblyName); + var isPass = FlowLibraryService.UnloadLibrary(assemblyName); return isPass; } else @@ -508,7 +513,7 @@ namespace Serein.NodeFlow.Env public bool TryGetMethodDetailsInfo(string assemblyName, string methodName, out MethodDetailsInfo? mdInfo) { - var isPass = _flowLibraryService.TryGetMethodDetails(assemblyName, methodName, out var md); + var isPass = FlowLibraryService.TryGetMethodDetails(assemblyName, methodName, out var md); if (!isPass || md is null) { mdInfo = null; @@ -534,7 +539,7 @@ namespace Serein.NodeFlow.Env /// public bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails? delegateDetails) { - return _flowLibraryService.TryGetDelegateDetails(assemblyName, methodName, out delegateDetails); + return FlowLibraryService.TryGetDelegateDetails(assemblyName, methodName, out delegateDetails); } /// @@ -662,7 +667,6 @@ namespace Serein.NodeFlow.Env /// public bool LoadNativeLibraryOfRuning(string file) { - return NativeDllHelper.LoadDll(file); } @@ -685,6 +689,11 @@ namespace Serein.NodeFlow.Env { } + + Task IFlowEnvironment.StartRemoteServerAsync(int port) + { + throw new NotImplementedException(); + } } diff --git a/NodeFlow/Model/Nodes/SingleFlowCallNode.cs b/NodeFlow/Model/Nodes/SingleFlowCallNode.cs index 06d9a2e..c40e1df 100644 --- a/NodeFlow/Model/Nodes/SingleFlowCallNode.cs +++ b/NodeFlow/Model/Nodes/SingleFlowCallNode.cs @@ -251,7 +251,7 @@ namespace Serein.NodeFlow.Model.Nodes var index = node.MethodDetails.MethodName.IndexOf('('); var methodName = tempName[..(index - 1)]; return GetApiInvokeName(node, methodName);*/ - FlowLibraryService service = node.Env.IOC.Get(); + IFlowLibraryService service = node.Env.IOC.Get(); if (service.TryGetMethodInfo(md.AssemblyName, md.MethodName, out var methodInfo)) { diff --git a/NodeFlow/Model/Nodes/SingleScriptNode.cs b/NodeFlow/Model/Nodes/SingleScriptNode.cs index 0dba74d..e65e9bf 100644 --- a/NodeFlow/Model/Nodes/SingleScriptNode.cs +++ b/NodeFlow/Model/Nodes/SingleScriptNode.cs @@ -196,7 +196,7 @@ namespace Serein.NodeFlow.Model.Nodes string returnTypeName = nodeInfo.CustomData?.ReturnTypeName ?? typeof(object); - var flowLibService = Env.IOC.Get(); + var flowLibService = Env.IOC.Get(); Type?[] argType = array.Select(info => string.IsNullOrWhiteSpace(info.ArgType) ? typeof(Unit) : Type.GetType(info.ArgType) diff --git a/NodeFlow/Model/Operations/OperationBase.cs b/NodeFlow/Model/Operations/OperationBase.cs index bffb958..e3e1b9b 100644 --- a/NodeFlow/Model/Operations/OperationBase.cs +++ b/NodeFlow/Model/Operations/OperationBase.cs @@ -56,7 +56,7 @@ namespace Serein.NodeFlow.Model.Operations /// 流程依赖服务 /// [AutoInjection] - protected FlowLibraryService flowLibraryManagement; + protected IFlowLibraryService flowLibraryManagement; /// /// 流程事件服务 diff --git a/NodeFlow/Serein.NodeFlow.csproj b/NodeFlow/Serein.NodeFlow.csproj index c4bffb3..1575dce 100644 --- a/NodeFlow/Serein.NodeFlow.csproj +++ b/NodeFlow/Serein.NodeFlow.csproj @@ -79,8 +79,9 @@ - - + + + diff --git a/Workbench/ViewModels/FlowLibrarysViewModel.cs b/Workbench/ViewModels/FlowLibrarysViewModel.cs index c9297f5..4bbc598 100644 --- a/Workbench/ViewModels/FlowLibrarysViewModel.cs +++ b/Workbench/ViewModels/FlowLibrarysViewModel.cs @@ -2,6 +2,7 @@ using Serein.Library; using Serein.Library.Api; using Serein.NodeFlow.Env; +using Serein.NodeFlow.Services; using Serein.Workbench.Api; using Serein.Workbench.Models; using Serein.Workbench.Services; @@ -27,6 +28,9 @@ namespace Serein.Workbench.ViewModels this.flowEnvironment = flowEnvironment; FlowLibraryInfos = new ObservableCollection(); flowEEForwardingService.DllLoad += FlowEEForwardingService_OnDllLoad; + + + //var baseLibrary = App.GetService().LoadBaseLibrary(); } /// /// 加载文件依赖 diff --git a/Workbench/Views/ViewCanvasInfoView.xaml b/Workbench/Views/ViewCanvasInfoView.xaml index b03cc1f..a1cb698 100644 --- a/Workbench/Views/ViewCanvasInfoView.xaml +++ b/Workbench/Views/ViewCanvasInfoView.xaml @@ -6,6 +6,7 @@ xmlns:local="clr-namespace:Serein.Workbench.Views" xmlns:vm="clr-namespace:Serein.Workbench.ViewModels" xmlns:converter="clr-namespace:Serein.Workbench.Converters" + xmlns:template="clr-namespace:CXLims.Software.WPFTemplate" mc:Ignorable="d" d:DesignHeight="600" d:DesignWidth="300" d:DataContext="{d:DesignInstance vm:ViewCanvasInfoViewModel}"> @@ -117,7 +118,32 @@ - + + + + + + + + + + + + + +