diff --git a/FlowStartTool/FlowEnv.cs b/FlowStartTool/FlowEnv.cs index 0cfecba..ad624e2 100644 --- a/FlowStartTool/FlowEnv.cs +++ b/FlowStartTool/FlowEnv.cs @@ -27,7 +27,7 @@ namespace Serein.FlowStartTool Console.WriteLine($"{DateTime.Now} [{infoType}] : {value}{Environment.NewLine}"); }; - await flowEnvironment.StartRemoteServerAsync(7525); // 启动 web socket 监听远程请求 + //await flowEnvironment.StartRemoteServerAsync(7525); // 启动 web socket 监听远程请求 IsRuning = false; } diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs index f567fe2..fe5e0ba 100644 --- a/Library/Api/IFlowEnvironment.cs +++ b/Library/Api/IFlowEnvironment.cs @@ -179,19 +179,14 @@ namespace Serein.Library.Api /// public class LoadDllEventArgs : FlowEventArgs { - public LoadDllEventArgs(NodeLibraryInfo nodeLibraryInfo, List MethodDetailss) + public LoadDllEventArgs(FlowLibraryInfo nodeLibraryInfo) { this.NodeLibraryInfo = nodeLibraryInfo; - this.MethodDetailss = MethodDetailss; } /// /// 已加载了的程序集 /// - public NodeLibraryInfo NodeLibraryInfo { get;} - /// - /// dll文件中有效的流程方法描述 - /// - public List MethodDetailss { get;} + public FlowLibraryInfo NodeLibraryInfo { get;} } /// @@ -791,7 +786,7 @@ namespace Serein.Library.Api /// /// 是否全局中断 /// - bool IsGlobalInterrupt { get; } + bool _IsGlobalInterrupt { get; } /// /// 表示是否正在控制远程 diff --git a/Library/Extension/FlowModelExtension.cs b/Library/Extension/FlowModelExtension.cs index d71b314..3320261 100644 --- a/Library/Extension/FlowModelExtension.cs +++ b/Library/Extension/FlowModelExtension.cs @@ -1,13 +1,10 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Serein.Library.Api; +using Serein.Library.Api; using Serein.Library.Utils; using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; -using System.Xml.Linq; namespace Serein.Library { diff --git a/Library/SereinBaseFunction.cs b/Library/FlowBaseLibrary.cs similarity index 70% rename from Library/SereinBaseFunction.cs rename to Library/FlowBaseLibrary.cs index c26945c..a470cd6 100644 --- a/Library/SereinBaseFunction.cs +++ b/Library/FlowBaseLibrary.cs @@ -14,18 +14,21 @@ namespace Serein.Library /// 基础功能 /// [DynamicFlow(Name ="[基础功能]")] - public static class SereinBaseFunction + public static class FlowBaseLibrary { [NodeAction(NodeType.Action, "对象透传")] - public static object SereinTransmissionObject(object value) => value; + public static object TransmissionObject(object value) => value; [NodeAction(NodeType.Action, "键值对组装")] - public static Dictionary SereinKvDataCollection(string argName, - params object[] value) + public static Dictionary DictSet(string argNames, params object[] value) { - var names = argName.Split(';'); - var count = Math.Min(value.Length, names.Length); + var names = argNames.Split(';'); + if(value.Length != names.Length) + { + throw new ArgumentException("参数名称数量与入参数量不一致"); + } + var count = value.Length; var dict = new Dictionary(); for (int i = 0; i < count; i++) { @@ -35,13 +38,13 @@ namespace Serein.Library } [NodeAction(NodeType.Action, "数组组装")] - public static object[] SereinListDataCollection(params object[] value) + public static object[] ArraySet(params object[] value) { return value; } [NodeAction(NodeType.Action, "输出")] - public static object[] SereinConsole(params object[] value) + public static object[] Console(params object[] value) { foreach (var item in value) { @@ -51,7 +54,7 @@ namespace Serein.Library } [NodeAction(NodeType.Action, "逻辑分支")] - public static object SereinLogicalBranch([NodeParam(IsExplicit = false)]bool @bool, + public static object LogicalBranch([NodeParam(IsExplicit = false)]bool @bool, object t_value, object f_value) { @@ -59,7 +62,7 @@ namespace Serein.Library } [NodeAction(NodeType.Action, "文本拼接")] - public static string SereinTextJoin(params object[] value) + public static string TextJoin(params object[] value) { StringBuilder sb = new StringBuilder(); foreach (var item in value) @@ -83,19 +86,19 @@ namespace Serein.Library [NodeAction(NodeType.Action, "键值对动态构建对象")] - public static object SereinKvDataToObject(Dictionary dict, + public static object CreateDynamicObjectOfDict(Dictionary dict, string classTypeName = "newClass_dynamic", bool IsPrint = false) { if (!DynamicObjectHelper.TryResolve(dict, classTypeName, out var result)) { - Console.WriteLine("赋值过程中有错误,请检查属性名和类型!"); + System.Console.WriteLine("赋值过程中有错误,请检查属性名和类型!"); } else { if (IsPrint) { - Console.WriteLine("创建完成,正在打印结果"); + System.Console.WriteLine("创建完成,正在打印结果"); DynamicObjectHelper.PrintObjectProperties(result); } } @@ -104,7 +107,7 @@ namespace Serein.Library [NodeAction(NodeType.Action, "设置或更新全局数据")] - public static object SereinAddOrUpdateFlowGlobalData(string name, object data) + public static object AddOrUpdateFlowGlobalData(string name, object data) { SereinEnv.AddOrUpdateFlowGlobalData(name, data); return data; diff --git a/Library/FlowNode/LightweightFlowEnvironment.cs b/Library/FlowNode/LightweightFlowEnvironment.cs index 602e693..f1c8e1d 100644 --- a/Library/FlowNode/LightweightFlowEnvironment.cs +++ b/Library/FlowNode/LightweightFlowEnvironment.cs @@ -631,7 +631,7 @@ namespace Serein.Library public string ProjectFileLocation => throw new NotImplementedException(); - public bool IsGlobalInterrupt => throw new NotImplementedException(); + public bool _IsGlobalInterrupt => throw new NotImplementedException(); public bool IsControlRemoteEnv => throw new NotImplementedException(); diff --git a/Library/FlowNode/SereinProjectData.cs b/Library/FlowNode/SereinProjectData.cs index 91f99e6..163fc8e 100644 --- a/Library/FlowNode/SereinProjectData.cs +++ b/Library/FlowNode/SereinProjectData.cs @@ -12,13 +12,12 @@ namespace Serein.Library /// /// 环境方法信息 /// - public LibraryMds[] LibraryMds { get; set; } + public FlowLibraryInfo[] LibraryMds { get; set; } /// /// 项目信息 /// public SereinProjectData Project { get; set; } - // IOC节点对象信息 } @@ -26,16 +25,27 @@ namespace Serein.Library /// /// 程序集相关的方法信息 /// - public class LibraryMds + public class FlowLibraryInfo { /// /// 程序集名称 /// public string AssemblyName { get; set; } + + /// + /// 文件名 + /// + public string FileName { get; set; } + + /// + /// 路径 + /// + public string FilePath { get; set; } + /// /// 相关的方法详情 /// - public MethodDetailsInfo[] Mds { get; set; } + public List MethodInfos { get; set; } } @@ -57,7 +67,7 @@ namespace Serein.Library /// 依赖的DLL /// - public NodeLibraryInfo[] Librarys { get; set; } + public FlowLibraryInfo[] Librarys { get; set; } /// /// 画布集合 @@ -89,29 +99,16 @@ namespace Serein.Library } - +/* /// /// 项目依赖的程序集,项目文件相关 /// /// - public class NodeLibraryInfo + public class FlowLibraryInfo { - /// - /// 文件名 - /// - public string FileName { get; set; } - /// - /// 路径 - /// - public string FilePath { get; set; } - - /// - /// 所属的程序集名称 - /// - public string AssemblyName { get; set; } } - +*/ /// /// 节点信息,项目文件相关 diff --git a/Library/NodeAttribute.cs b/Library/NodeAttribute.cs index fcaf0df..4eadefc 100644 --- a/Library/NodeAttribute.cs +++ b/Library/NodeAttribute.cs @@ -1,4 +1,5 @@ using System; +using System.Text.RegularExpressions; namespace Serein.Library { @@ -85,9 +86,9 @@ namespace Serein.Library public sealed class NodeActionAttribute : Attribute { public NodeActionAttribute(NodeType methodDynamicType, - string methodTips = "", - bool scan = true, - string lockName = "") + string methodTips = "", + bool scan = true, + string lockName = "") { Scan = scan; MethodDynamicType = methodDynamicType; @@ -110,6 +111,10 @@ namespace Serein.Library /// 暂无意义 /// public string LockName; + /// + /// 分组名称,暂无意义 + /// + public string GroupName; } diff --git a/Library/Serein.Library.csproj b/Library/Serein.Library.csproj index a3436b5..214d2b1 100644 --- a/Library/Serein.Library.csproj +++ b/Library/Serein.Library.csproj @@ -1,16 +1,17 @@  - 1.2.1.1 - net8.0;net462 - ..\.\.Output - True SereinFow + 1.2.2 动态节点流、可视化编辑的基本依赖,支持导入C# DLL生成自定义节点,提供二次开发支持,适合用于可视化编程和流程设计 README.md https://github.com/fhhyyp/serein-flow MIT True + + net8.0;net462 + ..\.\.Output + True latest no @@ -22,6 +23,22 @@ .\obj\g + + 1701;1702;1573 + + + + 1701;1702;1573 + + + + 1701;1702;1573 + + + + 1701;1702;1573 + + @@ -45,7 +62,7 @@ - + diff --git a/Library/Utils/SereinIoc.cs b/Library/Utils/SereinIoc.cs index e81482a..1ed410c 100644 --- a/Library/Utils/SereinIoc.cs +++ b/Library/Utils/SereinIoc.cs @@ -1,5 +1,4 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Serein.Library.Api; +using Serein.Library.Api; using System; using System.Collections.Concurrent; using System.Collections.Generic; diff --git a/NodeFlow/Env/FlowEdit.cs b/NodeFlow/Env/FlowEdit.cs index 8307009..8dfd6d8 100644 --- a/NodeFlow/Env/FlowEdit.cs +++ b/NodeFlow/Env/FlowEdit.cs @@ -208,7 +208,7 @@ namespace Serein.NodeFlow.Env { CanvasInfo = new FlowCanvasDetailsInfo { - Name = $"Canvas {_add_canvas_count++}", + Name = string.IsNullOrWhiteSpace(canvasName) ? $"Canvas {_add_canvas_count++}" : canvasName, Width = width, Height = height, Guid = Guid.NewGuid().ToString(), diff --git a/NodeFlow/Env/FlowEnvironment.cs b/NodeFlow/Env/FlowEnvironment.cs index d23aa00..6e51104 100644 --- a/NodeFlow/Env/FlowEnvironment.cs +++ b/NodeFlow/Env/FlowEnvironment.cs @@ -135,7 +135,7 @@ namespace Serein.NodeFlow.Env public string ProjectFileLocation => currentFlowEnvironment.EnvName; /// - public bool IsGlobalInterrupt => currentFlowEnvironment.IsGlobalInterrupt; + public bool _IsGlobalInterrupt => currentFlowEnvironment._IsGlobalInterrupt; /// public bool IsControlRemoteEnv => currentFlowEnvironment.IsControlRemoteEnv; diff --git a/NodeFlow/Env/LocalFlowEnvironment.cs b/NodeFlow/Env/LocalFlowEnvironment.cs index eed67f7..a4ca601 100644 --- a/NodeFlow/Env/LocalFlowEnvironment.cs +++ b/NodeFlow/Env/LocalFlowEnvironment.cs @@ -2,6 +2,7 @@ using Serein.Library.Api; using Serein.Library.Utils; using Serein.Library.Utils.SereinExpression; +using Serein.NodeFlow.Model.Library; using Serein.NodeFlow.Services; using Serein.NodeFlow.Tool; using System.Text; @@ -38,13 +39,13 @@ namespace Serein.NodeFlow.Env Event = flowEnvironmentEvent; NodeMVVMManagement = nodeMVVMService; FlowEdit = flowEdit; - FlowLibraryService = flowLibraryManagement; IOC = sereinIOC; - this.flowModelService = flowModelService; FlowControl = flowControl; - this.flowOperationService = flowOperationService; - this.IsGlobalInterrupt = false; - this.flowEnvIOC = sereinIOC; + _flowLibraryService = flowLibraryManagement; + _flowModelService = flowModelService; + _flowOperationService = flowOperationService; + _IsGlobalInterrupt = false; + _flowEnvIOC = sereinIOC; } @@ -146,7 +147,7 @@ namespace Serein.NodeFlow.Env /// /// 是否全局中断 /// - public bool IsGlobalInterrupt { get; set; } + public bool _IsGlobalInterrupt { get; set; } /// /// 单例模式IOC容器,内部维护了一个实例字典,默认使用类型的FullName作为Key,如果以“接口-实现类”的方式注册,那么将使用接口类型的FullName作为Key。 @@ -185,22 +186,22 @@ namespace Serein.NodeFlow.Env /// /// local环境的IOC容器,主要用于注册本地环境的服务 /// - private ISereinIOC flowEnvIOC; + private ISereinIOC _flowEnvIOC; /// /// 通过程序集名称管理动态加载的程序集,用于节点创建提供方法描述,流程运行时提供Emit委托 /// - private readonly FlowLibraryService FlowLibraryService; + private readonly FlowLibraryService _flowLibraryService; /// /// 流程节点操作服务 /// - private readonly FlowOperationService flowOperationService; + private readonly FlowOperationService _flowOperationService; /// /// 流程画布、节点实体管理服务 /// - private readonly FlowModelService flowModelService; + private readonly FlowModelService _flowModelService; /* /// /// 环境加载的节点集合 @@ -253,7 +254,7 @@ namespace Serein.NodeFlow.Env public async Task GetEnvInfoAsync() { // 获取所有的程序集对应的方法信息(程序集相关的数据) - var libraryMdss = this.FlowLibraryService.GetAllLibraryMds().ToArray(); + var libraryMdss = this._flowLibraryService.GetAllLibraryMds().ToArray(); // 获取当前项目的信息(节点相关的数据) var project = await GetProjectInfoAsync(); // 远程连接获取远程环境项目信息 SereinEnv.WriteLine(InfoType.INFO, "已将当前环境信息发送到远程客户端"); @@ -328,8 +329,6 @@ namespace Serein.NodeFlow.Env throw; } - // - //await SetStartNodeAsync("", projectData.StartNode); // 设置起始节点 }); } @@ -428,9 +427,9 @@ namespace Serein.NodeFlow.Env { var projectData = new SereinProjectData() { - Librarys = this.FlowLibraryService.GetAllLibraryInfo().ToArray(), - Nodes = flowModelService.GetAllNodeModel().Select(node => node.ToInfo()).Where(info => info is not null).ToArray(), - Canvass = flowModelService.GetAllCanvasModel().Select(canvas => canvas.ToInfo()).ToArray(), + Librarys = this._flowLibraryService.GetAllLibraryInfo().ToArray(), + Nodes = _flowModelService.GetAllNodeModel().Select(node => node.ToInfo()).Where(info => info is not null).ToArray(), + Canvass = _flowModelService.GetAllCanvasModel().Select(canvas => canvas.ToInfo()).ToArray(), //StartNode = NodeModels.Values.FirstOrDefault(it => it.IsStart)?.Guid, }; @@ -445,24 +444,12 @@ namespace Serein.NodeFlow.Env /// public void LoadLibrary(string dllPath) { - try { - #region 检查是否已经加载本地依赖 - var thisAssembly = typeof(IFlowEnvironment).Assembly; - var thisAssemblyName = thisAssembly.GetName().Name; - if (!string.IsNullOrEmpty(thisAssemblyName) && FlowLibraryService.GetLibraryMdsOfAssmbly(thisAssemblyName).Count == 0) + var libraryInfo = _flowLibraryService.LoadFlowLibrary(dllPath); + if (libraryInfo is not null && libraryInfo.MethodInfos.Count > 0) { - var tmp = FlowLibraryService.LoadLibraryOfPath(thisAssembly.Location); - UIContextOperation?.Invoke(() => Event.OnDllLoad(new LoadDllEventArgs(tmp.Item1, tmp.Item2))); // 通知UI创建dll面板显示 - } - - #endregion - - (var libraryInfo, var mdInfos) = FlowLibraryService.LoadLibraryOfPath(dllPath); - if (mdInfos.Count > 0) - { - UIContextOperation?.Invoke(() => Event.OnDllLoad(new LoadDllEventArgs(libraryInfo, mdInfos))); // 通知UI创建dll面板显示 + UIContextOperation?.Invoke(() => Event.OnDllLoad(new LoadDllEventArgs(libraryInfo))); // 通知UI创建dll面板显示 } } catch (Exception ex) @@ -471,15 +458,15 @@ namespace Serein.NodeFlow.Env } } - /// + /* /// /// 加载本地程序集 /// /// - public void LoadLibrary(FlowLibrary flowLibrary) + public void LoadLibrary(FlowLibraryCache flowLibrary) { try { - (var libraryInfo, var mdInfos) = FlowLibraryService.LoadLibraryOfPath(flowLibrary); + libraryInfo = FlowLibraryService.LoadFlowLibrary(flowLibrary); if (mdInfos.Count > 0) { UIContextOperation?.Invoke(() => Event.OnDllLoad(new LoadDllEventArgs(libraryInfo, mdInfos))); // 通知UI创建dll面板显示 @@ -490,7 +477,7 @@ namespace Serein.NodeFlow.Env SereinEnv.WriteLine(InfoType.ERROR, $"无法加载DLL文件:{ex.Message}"); } - } + }*/ /// @@ -501,10 +488,10 @@ namespace Serein.NodeFlow.Env public bool TryUnloadLibrary(string assemblyName) { // 获取与此程序集相关的节点 - var groupedNodes = flowModelService.GetAllNodeModel().Where(node => !string.IsNullOrWhiteSpace(node.MethodDetails.AssemblyName) && node.MethodDetails.AssemblyName.Equals(assemblyName)).ToArray(); + 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 @@ -584,7 +571,7 @@ namespace Serein.NodeFlow.Env { var model = new FlowCanvasDetails(this); model.LoadInfo(info); - flowModelService.AddCanvasModel(model); + _flowModelService.AddCanvasModel(model); if(UIContextOperation is null) { @@ -608,7 +595,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; @@ -633,7 +620,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); } /// @@ -648,7 +635,7 @@ namespace Serein.NodeFlow.Env } this.UIContextOperation = uiContextOperation; IOC.Register(() => uiContextOperation).Build(); - + OnUIContextOperationSet(); } @@ -713,9 +700,6 @@ namespace Serein.NodeFlow.Env } - - - /// /// 从Guid获取画布 /// @@ -729,7 +713,7 @@ namespace Serein.NodeFlow.Env canvasDetails = null; return false; } - return flowModelService.TryGetCanvasModel(nodeGuid, out canvasDetails); + return _flowModelService.TryGetCanvasModel(nodeGuid, out canvasDetails); } @@ -746,7 +730,7 @@ namespace Serein.NodeFlow.Env nodeModel = null; return false; } - return flowModelService.TryGetNodeModel(nodeGuid, out nodeModel); + return _flowModelService.TryGetNodeModel(nodeGuid, out nodeModel); } @@ -777,6 +761,20 @@ namespace Serein.NodeFlow.Env #endregion + /// + /// 设置了 UIContextOperation 需要立刻执行的方法,用于加载基础库,创建第一个画布。 + /// + private void OnUIContextOperationSet() + { + var baseLibrary = _flowLibraryService.LoadBaseLibrary(); + if (baseLibrary is not null && baseLibrary.MethodInfos.Count > 0) + { + UIContextOperation?.Invoke(() => Event.OnDllLoad(new LoadDllEventArgs(baseLibrary))); // 通知UI创建dll面板显示 + } + + // 创建第一个画布 + FlowEdit.CreateCanvas("Default", 1920, 1080); + } } diff --git a/NodeFlow/FlowNodeExtension.cs b/NodeFlow/FlowNodeExtension.cs index 9cccdf7..b742b5e 100644 --- a/NodeFlow/FlowNodeExtension.cs +++ b/NodeFlow/FlowNodeExtension.cs @@ -97,9 +97,9 @@ namespace Serein.NodeFlow /// /// /// - public static NodeLibraryInfo ToLibrary(this NodeLibraryInfo libraryInfo) + public static FlowLibraryInfo ToLibrary(this FlowLibraryInfo libraryInfo) { - return new NodeLibraryInfo + return new FlowLibraryInfo { AssemblyName = libraryInfo.AssemblyName, FileName = libraryInfo.FileName, diff --git a/NodeFlow/Tool/FlowLibrary.cs b/NodeFlow/Model/Library/FlowLibraryCache.cs similarity index 68% rename from NodeFlow/Tool/FlowLibrary.cs rename to NodeFlow/Model/Library/FlowLibraryCache.cs index 0ab4664..fff9e40 100644 --- a/NodeFlow/Tool/FlowLibrary.cs +++ b/NodeFlow/Model/Library/FlowLibraryCache.cs @@ -12,52 +12,52 @@ using System.Reflection; using System.Text; using static System.Runtime.InteropServices.JavaScript.JSType; -namespace Serein.NodeFlow +namespace Serein.NodeFlow.Model.Library { - public class LibraryMdDd - { - public MethodDetails MethodDetails { get; } - public MethodInfo MethodInfo { get; } - public DelegateDetails DelegateDetails { get; } - - public LibraryMdDd(MethodInfo methodInfo, MethodDetails methodDetails, DelegateDetails delegateDetails) - { - MethodDetails = methodDetails; - MethodInfo = methodInfo; - DelegateDetails = delegateDetails; - } - } /// /// 加载在流程中的程序集依赖 /// - public class FlowLibrary + public class FlowLibraryCache { - public Assembly Assembly { get; private set; } - - //private readonly Action actionOfUnloadAssmbly; - /*, Action actionOfUnloadAssmbly*/ - //this.actionOfUnloadAssmbly = actionOfUnloadAssmbly; - - public FlowLibrary(Assembly assembly) + /// + /// 通过程序集创建一个流程库实例 + /// + /// + public FlowLibraryCache(Assembly assembly) { - this.Assembly = assembly; - this.FullName = Path.GetFileName(Assembly.Location); - - this.FilePath = Assembly.Location; + Assembly = assembly; + FullName = Path.GetFileName(Assembly.Location); + FilePath = Assembly.Location; } - public FlowLibrary(Assembly assembly, + /// + /// 通过动态程序集和文件路径创建一个流程库实例 + /// + /// + /// + public FlowLibraryCache(Assembly dynamicAssembly, string filePath) { - this.Assembly = assembly; - this.FullName = Path.GetFileName(filePath); ; - this.FilePath = filePath; + Assembly = dynamicAssembly; + FullName = Path.GetFileName(filePath); ; + FilePath = filePath; } + /// + /// 程序集本身 + /// + public Assembly Assembly { get; private set; } + + /// + /// 程序集全名 + /// public string FullName { get; private set; } + /// + /// 程序集文件路径 + /// public string FilePath { get; private set; } /// @@ -65,60 +65,33 @@ namespace Serein.NodeFlow /// Key : 方法名称 /// Value :方法详情 /// - public ConcurrentDictionary MethodDetailss { get; } = new ConcurrentDictionary(); - public ConcurrentDictionary MethodInfos { get; } = new ConcurrentDictionary(); + public Dictionary MethodDetailss { get; } = new Dictionary(); /// - /// 管理通过Emit动态构建的委托 - /// Key :方法名称 - /// Value :方法详情 + /// 加载程序集时创建的方法信息 /// - public ConcurrentDictionary DelegateDetailss { get; } = new ConcurrentDictionary(); + public Dictionary MethodInfos { get; } = new Dictionary(); /// - /// 记录不同的注册时机需要自动创建全局唯一实例的类型信息 + /// 缓存节点方法通Emit委托 + /// Key :方法名称 + /// Value :方法详情 /// - public ConcurrentDictionary> RegisterTypes { get; } = new ConcurrentDictionary>(); - + public Dictionary DelegateDetailss { get; } = new Dictionary(); /// - /// 卸载当前程序集以及附带的所有信息 + /// 用于流程启动时,在不同阶段(Init_Loading_Loaded)需要创建实例的类型信息 /// - public void Upload() - { - DelegateDetailss.Clear(); - RegisterTypes.Clear(); - MethodDetailss.Clear(); - //actionOfUnloadAssmbly?.Invoke(); - - } - - /// - /// 转为依赖信息 - /// - /// - public NodeLibraryInfo ToInfo() - { - var assemblyName = Assembly.GetName().Name; - return new NodeLibraryInfo - { - AssemblyName = assemblyName, - FileName = this.FullName, - FilePath = this.FilePath, - }; - - - } + public Dictionary> RegisterTypes { get; } = new Dictionary>(); /// /// 动态加载程序集 /// - /// 程序集本身 /// - public bool LoadAssembly() + public bool LoadFlowMethod() { - Assembly assembly = this.Assembly; + Assembly assembly = Assembly; #region 检查入参 @@ -132,7 +105,7 @@ namespace Serein.NodeFlow try { types = assembly.GetTypes().ToList(); // 获取程序集中的所有类型 - if (types.Count < 0) // 防止动态程序集中没有类型信息? + if (types.Count <= 0) { return false; } @@ -143,7 +116,7 @@ namespace Serein.NodeFlow var loaderExceptions = ex.LoaderExceptions; foreach (var loaderException in loaderExceptions) { - SereinEnv.WriteLine(InfoType.ERROR, loaderException?.Message); + SereinEnv.WriteLine(InfoType.ERROR, "加载失败 : " + loaderException?.Message); } return false; } @@ -160,8 +133,7 @@ namespace Serein.NodeFlow // Type : 具有 DynamicFlowAttribute 标记的类型 // string : 类型元数据 DynamicFlowAttribute 特性中的 Name 属性 - types = types.Where(type => type.GetCustomAttribute() is DynamicFlowAttribute dynamicFlowAttribute - && dynamicFlowAttribute.Scan).ToList(); + types = types.Where(type => type.GetCustomAttribute() is DynamicFlowAttribute df && df.Scan).ToList(); foreach (var type in types) { @@ -208,20 +180,16 @@ namespace Serein.NodeFlow { return false; } - // 简单排序一下 - //detailss = detailss.OrderBy(k => k.MethodDetails.MethodName,).ToList(); - - + // 简单排序一下 detailss.Sort((a, b) => string.Compare(a.MethodDetails.MethodName, b.MethodDetails.MethodName, StringComparison.OrdinalIgnoreCase)); + foreach (var item in detailss) { - SereinEnv.WriteLine(InfoType.INFO, "loading method : " + item.MethodDetails.MethodName); + SereinEnv.WriteLine(InfoType.INFO, "加载方法 : " + item.MethodDetails.MethodName); } - - //detailss.Sort((a, b) => string.Compare()); - + #region 加载成功,缓存所有方法、委托的信息 foreach (var item in detailss) { @@ -253,6 +221,36 @@ namespace Serein.NodeFlow } + /// + /// 卸载当前程序集以及附带的所有信息 + /// + public void Unload() + { + DelegateDetailss.Clear(); + MethodInfos.Clear(); + RegisterTypes.Clear(); + MethodDetailss.Clear(); + } + + /// + /// 转为依赖信息 + /// + /// + public FlowLibraryInfo ToInfo() + { + var assemblyName = Assembly.GetName().Name; + var mdInfos = MethodDetailss.Values.Select(x => x.ToInfo()).ToList(); + mdInfos.Sort((a, b) => string.Compare(a.MethodName, b.MethodName, StringComparison.OrdinalIgnoreCase)); + return new FlowLibraryInfo + { + AssemblyName = assemblyName, + FileName = FullName, + FilePath = FilePath, + MethodInfos = mdInfos.ToList(), + }; + } + + } } diff --git a/NodeFlow/Model/Library/LibraryMdDd.cs b/NodeFlow/Model/Library/LibraryMdDd.cs new file mode 100644 index 0000000..79cda80 --- /dev/null +++ b/NodeFlow/Model/Library/LibraryMdDd.cs @@ -0,0 +1,20 @@ +using Serein.Library; +using System.Reflection; + +namespace Serein.NodeFlow.Model.Library +{ + public class LibraryMdDd + { + public MethodDetails MethodDetails { get; } + public MethodInfo MethodInfo { get; } + public DelegateDetails DelegateDetails { get; } + + public LibraryMdDd(MethodInfo methodInfo, MethodDetails methodDetails, DelegateDetails delegateDetails) + { + MethodDetails = methodDetails; + MethodInfo = methodInfo; + DelegateDetails = delegateDetails; + } + } + +} diff --git a/NodeFlow/Model/Node/SingleScriptNode.cs b/NodeFlow/Model/Node/SingleScriptNode.cs index 816a5c9..be54bbc 100644 --- a/NodeFlow/Model/Node/SingleScriptNode.cs +++ b/NodeFlow/Model/Node/SingleScriptNode.cs @@ -231,7 +231,7 @@ namespace Serein.NodeFlow.Model var returnType = sereinScript.ParserScript(Script, argTypes); // 开始解析获取程序主节点 MethodDetails.ReturnType = returnType; - var scriptMethodInfo = sereinScript.ConvertCSharpCode(methodName, argTypes); + var scriptMethodInfo = sereinScript.ConvertCSharpCode(methodName, argTypes); return scriptMethodInfo; } catch (Exception ex) diff --git a/NodeFlow/Model/Operation/ContainerTakeOutNodeOperation.cs b/NodeFlow/Model/Operation/ContainerTakeOutNodeOperation.cs index 0d885ff..f6ced50 100644 --- a/NodeFlow/Model/Operation/ContainerTakeOutNodeOperation.cs +++ b/NodeFlow/Model/Operation/ContainerTakeOutNodeOperation.cs @@ -42,18 +42,18 @@ namespace Serein.NodeFlow.Model.Operation { if (!flowModelService.ContainsCanvasModel(CanvasGuid)) { - flowEnvironment.WriteLine(Library.InfoType.INFO, $"节点取出失败,目标画布不存在[{NodeGuid}]"); + flowEnvironment.WriteLine(Serein.Library.InfoType.WARN, $"节点取出失败,目标画布不存在[{NodeGuid}]"); return false; } // 获取目标节点与容器节点 if (!flowModelService.TryGetNodeModel(NodeGuid, out var nodeModel)) { - flowEnvironment.WriteLine(Library.InfoType.INFO, $"节点取出失败,目标节点不存在[{NodeGuid}]"); + flowEnvironment.WriteLine(Serein.Library.InfoType.WARN, $"节点取出失败,目标节点不存在[{NodeGuid}]"); return false; } if (nodeModel.ContainerNode is not INodeContainer containerNode) { - flowEnvironment.WriteLine(Library.InfoType.INFO, $"节点取出失败,节点并非容器节点[{nodeModel.Guid}]"); + flowEnvironment.WriteLine(Serein.Library.InfoType.WARN, $"节点取出失败,节点并非容器节点[{nodeModel.Guid}]"); return false; } Node = nodeModel; diff --git a/NodeFlow/Model/Operation/CreateNodeOperation.cs b/NodeFlow/Model/Operation/CreateNodeOperation.cs index d0caf9a..e90cd78 100644 --- a/NodeFlow/Model/Operation/CreateNodeOperation.cs +++ b/NodeFlow/Model/Operation/CreateNodeOperation.cs @@ -97,7 +97,7 @@ namespace Serein.NodeFlow.Model.Operation // 节点与画布互相绑定 nodeModel.CanvasDetails = flowCanvasDetails; - flowCanvasDetails.Nodes.Add(nodeModel); + flowCanvasDetails.Nodes = [..flowCanvasDetails.Nodes, nodeModel]; flowModelService.AddNodeModel(nodeModel); this.flowNode = nodeModel; diff --git a/NodeFlow/Model/Operation/RemoveNodeOperation.cs b/NodeFlow/Model/Operation/RemoveNodeOperation.cs index 59572cc..62cc7ce 100644 --- a/NodeFlow/Model/Operation/RemoveNodeOperation.cs +++ b/NodeFlow/Model/Operation/RemoveNodeOperation.cs @@ -1,15 +1,5 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Serein.Library; +using Serein.Library; using Serein.Library.Api; -using Serein.Script.Node; -using System; -using System.Collections.Generic; -using System.Data.Common; -using System.Linq; -using System.Reflection.Metadata; -using System.Text; -using System.Threading.Tasks; -using System.Xml.Linq; namespace Serein.NodeFlow.Model.Operation { diff --git a/NodeFlow/Serein.NodeFlow.csproj b/NodeFlow/Serein.NodeFlow.csproj index 4928697..23071fc 100644 --- a/NodeFlow/Serein.NodeFlow.csproj +++ b/NodeFlow/Serein.NodeFlow.csproj @@ -1,7 +1,7 @@  - 1.2.1 + 1.2.2 net8.0 enable enable @@ -52,6 +52,7 @@ + @@ -69,6 +70,8 @@ + + diff --git a/NodeFlow/Services/FlowLibraryService.cs b/NodeFlow/Services/FlowLibraryService.cs index a9d4b2f..4dcd363 100644 --- a/NodeFlow/Services/FlowLibraryService.cs +++ b/NodeFlow/Services/FlowLibraryService.cs @@ -2,13 +2,14 @@ using Serein.Library.Api; using Serein.Library.FlowNode; using Serein.Library.Utils; +using Serein.NodeFlow.Model.Library; +using Serein.NodeFlow.Tool; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; -using System.Runtime.Loader; using System.Text; using System.Threading.Tasks; using System.Xml.Linq; @@ -28,54 +29,95 @@ namespace Serein.NodeFlow.Services private readonly IFlowEnvironment flowEnvironment; /// - /// 缓存所有加载了的程序集 + /// 缓存流程依赖 /// - private readonly ConcurrentDictionary _myFlowLibrarys = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _flowLibraryCaches = new ConcurrentDictionary(); + + + private readonly ConcurrentDictionary _flowLibraryAssemblyContexts + = new ConcurrentDictionary(); + /// - /// 加载类库 + /// 每个类库下面至少需要有“Serein.Library.dll”类库依赖 /// /// /// - public (NodeLibraryInfo, List) LoadLibraryOfPath(string libraryfilePath) + private bool CheckBaseLibrary(string libraryfilePath, out string baseLibraryPath) { - var dir = Path.GetDirectoryName(libraryfilePath); // 获取目录路径 - var sereinFlowBaseLibraryPath = Path.Combine(dir, SereinBaseLibrary);// 每个类库下面至少需要有“Serein.Library.dll”类库依赖 + var sereinFlowBaseLibraryPath = Path.Combine(dir, SereinBaseLibrary); if (!Path.Exists(sereinFlowBaseLibraryPath)) { - throw new Exception($"从文件加载DLL失败,目标文件夹不存在{SereinBaseLibrary}文件" ); - } - - var flowAlc = new FlowLibraryAssemblyContext(sereinFlowBaseLibraryPath, Path.GetFileName(libraryfilePath)); - var assembly = flowAlc.LoadFromAssemblyPath(libraryfilePath); // 加载指定路径的程序集 - - var flowLibrary = new FlowLibrary(assembly); - try - { - var reulst = LoadFlowLibrary(flowLibrary); - return reulst; - } - catch (Exception) - { - flowAlc?.Unload(); // 卸载程序集 - flowAlc = null; - GC.Collect(); // 强制触发GC确保卸载成功 - GC.WaitForPendingFinalizers(); - throw; + baseLibraryPath = string.Empty; + return false; } + baseLibraryPath = sereinFlowBaseLibraryPath; + return true; } /// - /// 加载类库 + /// 加载基础依赖 /// - /// - /// - public (NodeLibraryInfo, List) LoadLibraryOfPath(FlowLibrary flowLibrary) + public FlowLibraryInfo LoadBaseLibrary() { - return LoadFlowLibrary(flowLibrary); + Assembly baseAssmbly = typeof(FlowBaseLibrary).Assembly; + var flowLibrary = new FlowLibraryCache(baseAssmbly); + flowLibrary.LoadFlowMethod(); + var assemblyName = baseAssmbly.GetName().Name; + if (string.IsNullOrEmpty(assemblyName)) + { + throw new Exception($"程序集\"{baseAssmbly}\"返回 Name 为 null"); + } + _flowLibraryCaches.TryAdd(assemblyName, flowLibrary); + return flowLibrary.ToInfo(); } + /// + /// 加载流程依赖 + /// + /// + /// + public FlowLibraryInfo? LoadFlowLibrary(string libraryfilePath) + { + if (!CheckBaseLibrary(libraryfilePath, out var baseLibraryPath)) + { + throw new Exception($"从文件加载DLL失败,目标文件夹不存在{SereinBaseLibrary}文件"); + } + FlowLibraryAssemblyContext flowAlc = new FlowLibraryAssemblyContext(baseLibraryPath, Path.GetFileName(libraryfilePath)); + var flowAssembly = flowAlc.LoadFromAssemblyPath(libraryfilePath); + if(flowAssembly is null) + { + throw new Exception($"从文件加载DLL失败,FlowLibraryAssemblyContext 加载的程序集为 null \"{libraryfilePath}\""); + } + + var flowLibrary = new FlowLibraryCache(flowAssembly); + var isSuccess = flowLibrary.LoadFlowMethod(); + if (!isSuccess) + { + flowAlc?.Unload(); // 卸载程序集 + GC.Collect(); // 强制触发GC确保卸载成功 + GC.WaitForPendingFinalizers(); + return null; + } + else + { + var assemblyName = flowAssembly.GetName().Name; + if (string.IsNullOrEmpty(assemblyName)) + { + flowLibrary.Unload(); + flowAlc?.Unload(); // 卸载程序集 + GC.Collect(); // 强制触发GC确保卸载成功 + GC.WaitForPendingFinalizers(); + return null; + throw new Exception($"程序集\"{flowAssembly}\"返回 Name 为 null"); + } + _flowLibraryCaches.TryAdd(assemblyName, flowLibrary); + return flowLibrary.ToInfo(); + } + } + + /// /// 卸载类库 /// @@ -83,11 +125,11 @@ namespace Serein.NodeFlow.Services /// public bool UnloadLibrary(string assemblyName) { - if (_myFlowLibrarys.Remove(assemblyName, out var flowLibrary)) + if (_flowLibraryCaches.Remove(assemblyName, out var flowLibrary)) { try { - flowLibrary.Upload(); // 尝试卸载 + flowLibrary.Unload(); // 尝试卸载 flowLibrary = null; return true; } @@ -104,6 +146,8 @@ namespace Serein.NodeFlow.Services } } + #region 获取流程依赖的相关方法 + /// /// 获取方法描述 /// @@ -118,7 +162,7 @@ namespace Serein.NodeFlow.Services methodInfo = null; return false; } - if (_myFlowLibrarys.TryGetValue(assemblyName, out var flowLibrary) + if (_flowLibraryCaches.TryGetValue(assemblyName, out var flowLibrary) && flowLibrary.MethodInfos.TryGetValue(methodName, out methodInfo)) { return true; @@ -130,7 +174,7 @@ namespace Serein.NodeFlow.Services } } - /// + /// /// 获取方法描述 /// /// 程序集名称 @@ -139,7 +183,7 @@ namespace Serein.NodeFlow.Services /// 是否获取成功 public bool TryGetMethodDetails(string assemblyName, string methodName, [MaybeNullWhen(false)] out MethodDetails md) { - if (_myFlowLibrarys.TryGetValue(assemblyName, out var flowLibrary) + if (_flowLibraryCaches.TryGetValue(assemblyName, out var flowLibrary) && flowLibrary.MethodDetailss.TryGetValue(methodName, out md)) { return true; @@ -160,7 +204,7 @@ namespace Serein.NodeFlow.Services /// 是否获取成功 public bool TryGetDelegateDetails(string assemblyName, string methodName, [MaybeNullWhen(false)] out DelegateDetails dd) { - if (_myFlowLibrarys.TryGetValue(assemblyName, out var flowLibrary) + if (_flowLibraryCaches.TryGetValue(assemblyName, out var flowLibrary) && flowLibrary.DelegateDetailss.TryGetValue(methodName, out dd)) { return true; @@ -182,7 +226,7 @@ namespace Serein.NodeFlow.Services { List mds = []; - foreach (var library in _myFlowLibrarys.Values) + foreach (var library in _flowLibraryCaches.Values) { var t_mds = library.MethodDetailss.Values.Where(it => it.MethodDynamicType == nodeType).ToList(); mds.AddRange(t_mds); @@ -197,7 +241,7 @@ namespace Serein.NodeFlow.Services public Dictionary> GetaAutoRegisterType() { Dictionary> rsTypes = new Dictionary>(); - foreach (var library in _myFlowLibrarys.Values) + foreach (var library in _flowLibraryCaches.Values) { foreach (var kv in library.RegisterTypes) { @@ -220,28 +264,26 @@ namespace Serein.NodeFlow.Services /// public List GetLibraryMdsOfAssmbly(string assemblyName) { - if (_myFlowLibrarys.TryGetValue(assemblyName, out var flowLibrary)) + if (_flowLibraryCaches.TryGetValue(assemblyName, out var flowLibrary)) { return flowLibrary.MethodDetailss.Values.ToList(); } return []; } - - /// - /// 获取所有方法信息,用于保存项目时调用 + /// 获取流程方法信息,用于保存项目时调用 /// /// - public List GetAllLibraryMds() + public List GetAllLibraryMds() { - List mds = new List(); - foreach (FlowLibrary library in _myFlowLibrarys.Values) + List mds = new List(); + foreach (FlowLibraryCache library in _flowLibraryCaches.Values) { - var tmp = new LibraryMds + var tmp = new FlowLibraryInfo { AssemblyName = library.FullName, - Mds = library.MethodDetailss.Values.Select(md => md.ToInfo()).ToArray() + MethodInfos = library.MethodDetailss.Values.Select(md => md.ToInfo()).ToList() }; mds.Add(tmp); } @@ -253,11 +295,11 @@ namespace Serein.NodeFlow.Services /// 序列化当前项目的依赖信息、节点信息,用于远程登录的场景,需要将依赖信息从本地(受控端)发送到远程(主控端) /// /// - public List GetAllLibraryInfo() + public List GetAllLibraryInfo() { - return _myFlowLibrarys.Values.Select(library => library.ToInfo()).ToList(); + return _flowLibraryCaches.Values.Select(library => library.ToInfo()).ToList(); } - + #endregion #region 功能性方法 @@ -266,132 +308,7 @@ namespace Serein.NodeFlow.Services /// public readonly static string SereinBaseLibrary = $"{nameof(Serein)}.{nameof(Library)}.dll"; - //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) - { - // 加载基础依赖 - flowLibrary = new FlowLibrary(typeof(IFlowEnvironment).Assembly); - } - - var assmblyName = assembly.GetName().Name; - if (!string.IsNullOrEmpty(assmblyName) && _myFlowLibrarys.ContainsKey(assmblyName)) - { - throw new Exception($"程序集[{assembly.GetName().FullName}]已经加载过!"); - } - - var loadResult = flowLibrary.LoadAssembly(); // 加载程序集 - if (loadResult) - { - var assemblyName = assembly.GetName().Name; - if (string.IsNullOrEmpty(assemblyName)) - { - throw new Exception($"程序集[{assembly.GetName().FullName}]加载失败,没有程序集名称"); - } - _myFlowLibrarys.TryAdd(assemblyName, flowLibrary); - - List mdInfos = flowLibrary.MethodDetailss.Values.Select(md => md.ToInfo()).ToList(); - mdInfos.Sort((a, b) => string.Compare(a.MethodName, b.MethodName, StringComparison.OrdinalIgnoreCase)); - - (NodeLibraryInfo, List) result = (flowLibrary.ToInfo(), mdInfos); - return result; - } - else - { - throw new Exception($"程序集[{assembly.GetName().FullName}]加载失败"); - } - } - - #endregion } - - /// - /// 流程依赖加载 - /// - public class FlowLibraryAssemblyContext : AssemblyLoadContext - { - private readonly AssemblyDependencyResolver _resolver; - - /// - /// 创建新的加载上下文 - /// - /// 类库路径 - /// - public FlowLibraryAssemblyContext(string sereinFlowLibraryPath, string name) : base(name, isCollectible: true) - { - _resolver = new AssemblyDependencyResolver(sereinFlowLibraryPath); - } - - protected override Assembly? Load(AssemblyName assemblyName) - { - string? assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName); - if (!string.IsNullOrEmpty(assemblyPath)) - { - var assembly = Default.LoadFromAssemblyPath(assemblyPath); - //var assembly = LoadFromAssemblyPath(assemblyPath); - return assembly; - } - else - { - return Default.Assemblies.FirstOrDefault(x => x.FullName == assemblyName.FullName); - } - - // return null; - - // 构建依赖项的路径 - //string assemblyPath = Path.Combine(AppContext.BaseDirectory, assemblyName.Name + ".dll"); - //if (File.Exists(assemblyPath)) - //{ - // return LoadFromAssemblyPath(assemblyPath); - //} - //assemblyPath = Path.Combine(filePath, assemblyName.Name + ".dll"); - //if (File.Exists(assemblyPath)) - //{ - // return LoadFromAssemblyPath(assemblyPath); - //} - - //return null; // 如果没有找到,返回 null - } - } - //public static class PluginAssemblyContextExtensions - //{ - - // public static Assembly FromAssemblyPath(this AssemblyLoadContext context, string path) - // { - - // return context.LoadFromAssemblyPath(path); - - // } - - //} } diff --git a/NodeFlow/Tool/DynamicCompiler.cs b/NodeFlow/Tool/DynamicCompiler.cs index 9d3d7fc..0761b14 100644 --- a/NodeFlow/Tool/DynamicCompiler.cs +++ b/NodeFlow/Tool/DynamicCompiler.cs @@ -1,13 +1,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Emit; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; using System.Reflection; -using System.Text; -using System.Threading.Tasks; namespace Serein.NodeFlow.Tool { diff --git a/NodeFlow/Tool/FlowLibraryAssemblyContext.cs b/NodeFlow/Tool/FlowLibraryAssemblyContext.cs new file mode 100644 index 0000000..28d9596 --- /dev/null +++ b/NodeFlow/Tool/FlowLibraryAssemblyContext.cs @@ -0,0 +1,59 @@ +using System.Reflection; +using System.Runtime.Loader; + +namespace Serein.NodeFlow.Tool +{ + /// + /// 流程依赖加载 + /// + public class FlowLibraryAssemblyContext : AssemblyLoadContext + { + private readonly AssemblyDependencyResolver _resolver; + + /// + /// 创建新的加载上下文 + /// + /// 流程基础依赖类库路径 + /// + public FlowLibraryAssemblyContext(string baseLibraryPath, string name) : base(name, isCollectible: true) + { + _resolver = new AssemblyDependencyResolver(baseLibraryPath); + } + + /// + /// 加载指定的程序集 + /// + /// + /// + protected override Assembly? Load(AssemblyName assemblyName) + { + string? assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName); // 加载程序集 + if (!string.IsNullOrEmpty(assemblyPath)) + { + var assembly = Default.LoadFromAssemblyPath(assemblyPath); // 通过默认方式进行加载程序集及相关依赖 + //var assembly = LoadFromAssemblyPath(assemblyPath); + return assembly; + } + else + { + return Default.Assemblies.FirstOrDefault(x => x.FullName == assemblyName.FullName); + } + + // return null; + + // 构建依赖项的路径 + //string assemblyPath = Path.Combine(AppContext.BaseDirectory, assemblyName.Name + ".dll"); + //if (File.Exists(assemblyPath)) + //{ + // return LoadFromAssemblyPath(assemblyPath); + //} + //assemblyPath = Path.Combine(filePath, assemblyName.Name + ".dll"); + //if (File.Exists(assemblyPath)) + //{ + // return LoadFromAssemblyPath(assemblyPath); + //} + + //return null; // 如果没有找到,返回 null + } + } +} diff --git a/NodeFlow/Tool/FlowLibraryAssemblyContext2.cs b/NodeFlow/Tool/FlowLibraryAssemblyContext2.cs new file mode 100644 index 0000000..2d71e74 --- /dev/null +++ b/NodeFlow/Tool/FlowLibraryAssemblyContext2.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using System.Text; +using System.Threading.Tasks; + +namespace Serein.NodeFlow.Model.Library +{ + + /// + /// 流程依赖加载 + /// + public class FlowLibraryAssemblyContext : AssemblyLoadContext + { + private readonly AssemblyDependencyResolver _resolver; + + /// + /// 创建新的加载上下文 + /// + /// 类库路径 + /// + public FlowLibraryAssemblyContext(string sereinFlowLibraryPath, string name) : base(name, isCollectible: true) + { + _resolver = new AssemblyDependencyResolver(sereinFlowLibraryPath); + } + + protected override Assembly? Load(AssemblyName assemblyName) + { + string? assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName); + if (!string.IsNullOrEmpty(assemblyPath)) + { + var assembly = Default.LoadFromAssemblyPath(assemblyPath); + //var assembly = LoadFromAssemblyPath(assemblyPath); + return assembly; + } + else + { + return Default.Assemblies.FirstOrDefault(x => x.FullName == assemblyName.FullName); + } + } + } +} diff --git a/Serein.Extend.NewtonsoftJson/NewtonsoftJsonExtend.cs b/Serein.Extend.NewtonsoftJson/NewtonsoftJsonExtend.cs index 6cb955f..c3957c5 100644 --- a/Serein.Extend.NewtonsoftJson/NewtonsoftJsonExtend.cs +++ b/Serein.Extend.NewtonsoftJson/NewtonsoftJsonExtend.cs @@ -1,10 +1,4 @@ -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Serein.Library.Utils; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Serein.Library.Utils; namespace Serein.Extend.NewtonsoftJson { diff --git a/Serein.Extend.NewtonsoftJson/Serein.Extend.NewtonsoftJson.csproj b/Serein.Extend.NewtonsoftJson/Serein.Extend.NewtonsoftJson.csproj index a3f1f49..0dfec00 100644 --- a/Serein.Extend.NewtonsoftJson/Serein.Extend.NewtonsoftJson.csproj +++ b/Serein.Extend.NewtonsoftJson/Serein.Extend.NewtonsoftJson.csproj @@ -5,6 +5,15 @@ enable latest enable + ..\.\.Output + + 为 SereinFlow 提供的 JSON 扩展 + 1.0.0 + 通过 NewtonsoftJson 实现JSON门户扩展,用于解决 Serein.Proto.* 项目下需要 JSON 序列化与反序列化的场景 + MIT + True + True + diff --git a/Serein.Library.MyGenerator/Serein.Library.NodeGenerator.csproj b/Serein.Library.MyGenerator/Serein.Library.NodeGenerator.csproj index 0505845..0579a29 100644 --- a/Serein.Library.MyGenerator/Serein.Library.NodeGenerator.csproj +++ b/Serein.Library.MyGenerator/Serein.Library.NodeGenerator.csproj @@ -25,7 +25,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - +