mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-05-02 05:11:27 +08:00
重新设计了FlowLIbrary相关类;为工作台默认添加了基础依赖、默认画布。
This commit is contained in:
@@ -27,7 +27,7 @@ namespace Serein.FlowStartTool
|
|||||||
Console.WriteLine($"{DateTime.Now} [{infoType}] : {value}{Environment.NewLine}");
|
Console.WriteLine($"{DateTime.Now} [{infoType}] : {value}{Environment.NewLine}");
|
||||||
};
|
};
|
||||||
|
|
||||||
await flowEnvironment.StartRemoteServerAsync(7525); // 启动 web socket 监听远程请求
|
//await flowEnvironment.StartRemoteServerAsync(7525); // 启动 web socket 监听远程请求
|
||||||
IsRuning = false;
|
IsRuning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -179,19 +179,14 @@ namespace Serein.Library.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class LoadDllEventArgs : FlowEventArgs
|
public class LoadDllEventArgs : FlowEventArgs
|
||||||
{
|
{
|
||||||
public LoadDllEventArgs(NodeLibraryInfo nodeLibraryInfo, List<MethodDetailsInfo> MethodDetailss)
|
public LoadDllEventArgs(FlowLibraryInfo nodeLibraryInfo)
|
||||||
{
|
{
|
||||||
this.NodeLibraryInfo = nodeLibraryInfo;
|
this.NodeLibraryInfo = nodeLibraryInfo;
|
||||||
this.MethodDetailss = MethodDetailss;
|
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 已加载了的程序集
|
/// 已加载了的程序集
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public NodeLibraryInfo NodeLibraryInfo { get;}
|
public FlowLibraryInfo NodeLibraryInfo { get;}
|
||||||
/// <summary>
|
|
||||||
/// dll文件中有效的流程方法描述
|
|
||||||
/// </summary>
|
|
||||||
public List<MethodDetailsInfo> MethodDetailss { get;}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -791,7 +786,7 @@ namespace Serein.Library.Api
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否全局中断
|
/// 是否全局中断
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsGlobalInterrupt { get; }
|
bool _IsGlobalInterrupt { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>表示是否正在控制远程</para>
|
/// <para>表示是否正在控制远程</para>
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Serein.Library.Api;
|
||||||
using Serein.Library.Api;
|
|
||||||
using Serein.Library.Utils;
|
using Serein.Library.Utils;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace Serein.Library
|
namespace Serein.Library
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,18 +14,21 @@ namespace Serein.Library
|
|||||||
/// 基础功能
|
/// 基础功能
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DynamicFlow(Name ="[基础功能]")]
|
[DynamicFlow(Name ="[基础功能]")]
|
||||||
public static class SereinBaseFunction
|
public static class FlowBaseLibrary
|
||||||
{
|
{
|
||||||
|
|
||||||
[NodeAction(NodeType.Action, "对象透传")]
|
[NodeAction(NodeType.Action, "对象透传")]
|
||||||
public static object SereinTransmissionObject(object value) => value;
|
public static object TransmissionObject(object value) => value;
|
||||||
|
|
||||||
[NodeAction(NodeType.Action, "键值对组装")]
|
[NodeAction(NodeType.Action, "键值对组装")]
|
||||||
public static Dictionary<string, object> SereinKvDataCollection(string argName,
|
public static Dictionary<string, object> DictSet(string argNames, params object[] value)
|
||||||
params object[] value)
|
|
||||||
{
|
{
|
||||||
var names = argName.Split(';');
|
var names = argNames.Split(';');
|
||||||
var count = Math.Min(value.Length, names.Length);
|
if(value.Length != names.Length)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("参数名称数量与入参数量不一致");
|
||||||
|
}
|
||||||
|
var count = value.Length;
|
||||||
var dict = new Dictionary<string, object>();
|
var dict = new Dictionary<string, object>();
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
@@ -35,13 +38,13 @@ namespace Serein.Library
|
|||||||
}
|
}
|
||||||
|
|
||||||
[NodeAction(NodeType.Action, "数组组装")]
|
[NodeAction(NodeType.Action, "数组组装")]
|
||||||
public static object[] SereinListDataCollection(params object[] value)
|
public static object[] ArraySet(params object[] value)
|
||||||
{
|
{
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NodeAction(NodeType.Action, "输出")]
|
[NodeAction(NodeType.Action, "输出")]
|
||||||
public static object[] SereinConsole(params object[] value)
|
public static object[] Console(params object[] value)
|
||||||
{
|
{
|
||||||
foreach (var item in value)
|
foreach (var item in value)
|
||||||
{
|
{
|
||||||
@@ -51,7 +54,7 @@ namespace Serein.Library
|
|||||||
}
|
}
|
||||||
|
|
||||||
[NodeAction(NodeType.Action, "逻辑分支")]
|
[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 t_value,
|
||||||
object f_value)
|
object f_value)
|
||||||
{
|
{
|
||||||
@@ -59,7 +62,7 @@ namespace Serein.Library
|
|||||||
}
|
}
|
||||||
|
|
||||||
[NodeAction(NodeType.Action, "文本拼接")]
|
[NodeAction(NodeType.Action, "文本拼接")]
|
||||||
public static string SereinTextJoin(params object[] value)
|
public static string TextJoin(params object[] value)
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
foreach (var item in value)
|
foreach (var item in value)
|
||||||
@@ -83,19 +86,19 @@ namespace Serein.Library
|
|||||||
|
|
||||||
|
|
||||||
[NodeAction(NodeType.Action, "键值对动态构建对象")]
|
[NodeAction(NodeType.Action, "键值对动态构建对象")]
|
||||||
public static object SereinKvDataToObject(Dictionary<string, object> dict,
|
public static object CreateDynamicObjectOfDict(Dictionary<string, object> dict,
|
||||||
string classTypeName = "newClass_dynamic",
|
string classTypeName = "newClass_dynamic",
|
||||||
bool IsPrint = false)
|
bool IsPrint = false)
|
||||||
{
|
{
|
||||||
if (!DynamicObjectHelper.TryResolve(dict, classTypeName, out var result))
|
if (!DynamicObjectHelper.TryResolve(dict, classTypeName, out var result))
|
||||||
{
|
{
|
||||||
Console.WriteLine("赋值过程中有错误,请检查属性名和类型!");
|
System.Console.WriteLine("赋值过程中有错误,请检查属性名和类型!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (IsPrint)
|
if (IsPrint)
|
||||||
{
|
{
|
||||||
Console.WriteLine("创建完成,正在打印结果");
|
System.Console.WriteLine("创建完成,正在打印结果");
|
||||||
DynamicObjectHelper.PrintObjectProperties(result);
|
DynamicObjectHelper.PrintObjectProperties(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,7 +107,7 @@ namespace Serein.Library
|
|||||||
|
|
||||||
|
|
||||||
[NodeAction(NodeType.Action, "设置或更新全局数据")]
|
[NodeAction(NodeType.Action, "设置或更新全局数据")]
|
||||||
public static object SereinAddOrUpdateFlowGlobalData(string name, object data)
|
public static object AddOrUpdateFlowGlobalData(string name, object data)
|
||||||
{
|
{
|
||||||
SereinEnv.AddOrUpdateFlowGlobalData(name, data);
|
SereinEnv.AddOrUpdateFlowGlobalData(name, data);
|
||||||
return data;
|
return data;
|
||||||
@@ -631,7 +631,7 @@ namespace Serein.Library
|
|||||||
|
|
||||||
public string ProjectFileLocation => throw new NotImplementedException();
|
public string ProjectFileLocation => throw new NotImplementedException();
|
||||||
|
|
||||||
public bool IsGlobalInterrupt => throw new NotImplementedException();
|
public bool _IsGlobalInterrupt => throw new NotImplementedException();
|
||||||
|
|
||||||
public bool IsControlRemoteEnv => throw new NotImplementedException();
|
public bool IsControlRemoteEnv => throw new NotImplementedException();
|
||||||
|
|
||||||
|
|||||||
@@ -12,13 +12,12 @@ namespace Serein.Library
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 环境方法信息
|
/// 环境方法信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public LibraryMds[] LibraryMds { get; set; }
|
public FlowLibraryInfo[] LibraryMds { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 项目信息
|
/// 项目信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SereinProjectData Project { get; set; }
|
public SereinProjectData Project { get; set; }
|
||||||
|
|
||||||
// IOC节点对象信息
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -26,16 +25,27 @@ namespace Serein.Library
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 程序集相关的方法信息
|
/// 程序集相关的方法信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LibraryMds
|
public class FlowLibraryInfo
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 程序集名称
|
/// 程序集名称
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string AssemblyName { get; set; }
|
public string AssemblyName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件名
|
||||||
|
/// </summary>
|
||||||
|
public string FileName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 路径
|
||||||
|
/// </summary>
|
||||||
|
public string FilePath { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 相关的方法详情
|
/// 相关的方法详情
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public MethodDetailsInfo[] Mds { get; set; }
|
public List<MethodDetailsInfo> MethodInfos { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +67,7 @@ namespace Serein.Library
|
|||||||
/// 依赖的DLL
|
/// 依赖的DLL
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
||||||
public NodeLibraryInfo[] Librarys { get; set; }
|
public FlowLibraryInfo[] Librarys { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 画布集合
|
/// 画布集合
|
||||||
@@ -89,29 +99,16 @@ namespace Serein.Library
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 项目依赖的程序集,项目文件相关
|
/// 项目依赖的程序集,项目文件相关
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <summary>
|
/// <summary>
|
||||||
public class NodeLibraryInfo
|
public class FlowLibraryInfo
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 文件名
|
|
||||||
/// </summary>
|
|
||||||
public string FileName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 路径
|
|
||||||
/// </summary>
|
|
||||||
public string FilePath { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 所属的程序集名称
|
|
||||||
/// </summary>
|
|
||||||
public string AssemblyName { get; set; }
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 节点信息,项目文件相关
|
/// 节点信息,项目文件相关
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace Serein.Library
|
namespace Serein.Library
|
||||||
{
|
{
|
||||||
@@ -85,9 +86,9 @@ namespace Serein.Library
|
|||||||
public sealed class NodeActionAttribute : Attribute
|
public sealed class NodeActionAttribute : Attribute
|
||||||
{
|
{
|
||||||
public NodeActionAttribute(NodeType methodDynamicType,
|
public NodeActionAttribute(NodeType methodDynamicType,
|
||||||
string methodTips = "",
|
string methodTips = "",
|
||||||
bool scan = true,
|
bool scan = true,
|
||||||
string lockName = "")
|
string lockName = "")
|
||||||
{
|
{
|
||||||
Scan = scan;
|
Scan = scan;
|
||||||
MethodDynamicType = methodDynamicType;
|
MethodDynamicType = methodDynamicType;
|
||||||
@@ -110,6 +111,10 @@ namespace Serein.Library
|
|||||||
/// 暂无意义
|
/// 暂无意义
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string LockName;
|
public string LockName;
|
||||||
|
/// <summary>
|
||||||
|
/// 分组名称,暂无意义
|
||||||
|
/// </summary>
|
||||||
|
public string GroupName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>1.2.1.1</Version>
|
|
||||||
<TargetFrameworks>net8.0;net462</TargetFrameworks>
|
|
||||||
<BaseOutputPath>..\.\.Output</BaseOutputPath>
|
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
|
||||||
<Title>SereinFow</Title>
|
<Title>SereinFow</Title>
|
||||||
|
<Version>1.2.2</Version>
|
||||||
<Description>动态节点流、可视化编辑的基本依赖,支持导入C# DLL生成自定义节点,提供二次开发支持,适合用于可视化编程和流程设计</Description>
|
<Description>动态节点流、可视化编辑的基本依赖,支持导入C# DLL生成自定义节点,提供二次开发支持,适合用于可视化编程和流程设计</Description>
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<RepositoryUrl>https://github.com/fhhyyp/serein-flow</RepositoryUrl>
|
<RepositoryUrl>https://github.com/fhhyyp/serein-flow</RepositoryUrl>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||||
|
|
||||||
|
<TargetFrameworks>net8.0;net462</TargetFrameworks>
|
||||||
|
<BaseOutputPath>..\.\.Output</BaseOutputPath>
|
||||||
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<SatelliteResourceLanguages>no</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>no</SatelliteResourceLanguages>
|
||||||
|
|
||||||
@@ -22,6 +23,22 @@
|
|||||||
<CompilerGeneratedFilesOutputPath>.\obj\g</CompilerGeneratedFilesOutputPath>
|
<CompilerGeneratedFilesOutputPath>.\obj\g</CompilerGeneratedFilesOutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0|AnyCPU'">
|
||||||
|
<NoWarn>1701;1702;1573</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net462|AnyCPU'">
|
||||||
|
<NoWarn>1701;1702;1573</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0|AnyCPU'">
|
||||||
|
<NoWarn>1701;1702;1573</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net462|AnyCPU'">
|
||||||
|
<NoWarn>1701;1702;1573</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Remove="Http\**" />
|
<Compile Remove="Http\**" />
|
||||||
<Compile Remove="Network\**" />
|
<Compile Remove="Network\**" />
|
||||||
@@ -45,7 +62,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="9.0.0" />
|
||||||
<PackageReference Include="System.IO.Ports" Version="9.0.7" />
|
<PackageReference Include="System.IO.Ports" Version="9.0.7" />
|
||||||
<PackageReference Include="System.Reactive" Version="6.0.1" />
|
<PackageReference Include="System.Reactive" Version="6.0.1" />
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Serein.Library.Api;
|
||||||
using Serein.Library.Api;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
{
|
{
|
||||||
CanvasInfo = new FlowCanvasDetailsInfo
|
CanvasInfo = new FlowCanvasDetailsInfo
|
||||||
{
|
{
|
||||||
Name = $"Canvas {_add_canvas_count++}",
|
Name = string.IsNullOrWhiteSpace(canvasName) ? $"Canvas {_add_canvas_count++}" : canvasName,
|
||||||
Width = width,
|
Width = width,
|
||||||
Height = height,
|
Height = height,
|
||||||
Guid = Guid.NewGuid().ToString(),
|
Guid = Guid.NewGuid().ToString(),
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
public string ProjectFileLocation => currentFlowEnvironment.EnvName;
|
public string ProjectFileLocation => currentFlowEnvironment.EnvName;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public bool IsGlobalInterrupt => currentFlowEnvironment.IsGlobalInterrupt;
|
public bool _IsGlobalInterrupt => currentFlowEnvironment._IsGlobalInterrupt;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public bool IsControlRemoteEnv => currentFlowEnvironment.IsControlRemoteEnv;
|
public bool IsControlRemoteEnv => currentFlowEnvironment.IsControlRemoteEnv;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Serein.Library.Api;
|
using Serein.Library.Api;
|
||||||
using Serein.Library.Utils;
|
using Serein.Library.Utils;
|
||||||
using Serein.Library.Utils.SereinExpression;
|
using Serein.Library.Utils.SereinExpression;
|
||||||
|
using Serein.NodeFlow.Model.Library;
|
||||||
using Serein.NodeFlow.Services;
|
using Serein.NodeFlow.Services;
|
||||||
using Serein.NodeFlow.Tool;
|
using Serein.NodeFlow.Tool;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -38,13 +39,13 @@ namespace Serein.NodeFlow.Env
|
|||||||
Event = flowEnvironmentEvent;
|
Event = flowEnvironmentEvent;
|
||||||
NodeMVVMManagement = nodeMVVMService;
|
NodeMVVMManagement = nodeMVVMService;
|
||||||
FlowEdit = flowEdit;
|
FlowEdit = flowEdit;
|
||||||
FlowLibraryService = flowLibraryManagement;
|
|
||||||
IOC = sereinIOC;
|
IOC = sereinIOC;
|
||||||
this.flowModelService = flowModelService;
|
|
||||||
FlowControl = flowControl;
|
FlowControl = flowControl;
|
||||||
this.flowOperationService = flowOperationService;
|
_flowLibraryService = flowLibraryManagement;
|
||||||
this.IsGlobalInterrupt = false;
|
_flowModelService = flowModelService;
|
||||||
this.flowEnvIOC = sereinIOC;
|
_flowOperationService = flowOperationService;
|
||||||
|
_IsGlobalInterrupt = false;
|
||||||
|
_flowEnvIOC = sereinIOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -146,7 +147,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否全局中断
|
/// 是否全局中断
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsGlobalInterrupt { get; set; }
|
public bool _IsGlobalInterrupt { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>单例模式IOC容器,内部维护了一个实例字典,默认使用类型的FullName作为Key,如果以“接口-实现类”的方式注册,那么将使用接口类型的FullName作为Key。</para>
|
/// <para>单例模式IOC容器,内部维护了一个实例字典,默认使用类型的FullName作为Key,如果以“接口-实现类”的方式注册,那么将使用接口类型的FullName作为Key。</para>
|
||||||
@@ -185,22 +186,22 @@ namespace Serein.NodeFlow.Env
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// local环境的IOC容器,主要用于注册本地环境的服务
|
/// local环境的IOC容器,主要用于注册本地环境的服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ISereinIOC flowEnvIOC;
|
private ISereinIOC _flowEnvIOC;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 通过程序集名称管理动态加载的程序集,用于节点创建提供方法描述,流程运行时提供Emit委托
|
/// 通过程序集名称管理动态加载的程序集,用于节点创建提供方法描述,流程运行时提供Emit委托
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly FlowLibraryService FlowLibraryService;
|
private readonly FlowLibraryService _flowLibraryService;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 流程节点操作服务
|
/// 流程节点操作服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly FlowOperationService flowOperationService;
|
private readonly FlowOperationService _flowOperationService;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 流程画布、节点实体管理服务
|
/// 流程画布、节点实体管理服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly FlowModelService flowModelService;
|
private readonly FlowModelService _flowModelService;
|
||||||
|
|
||||||
/* /// <summary>
|
/* /// <summary>
|
||||||
/// 环境加载的节点集合
|
/// 环境加载的节点集合
|
||||||
@@ -253,7 +254,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
public async Task<FlowEnvInfo> GetEnvInfoAsync()
|
public async Task<FlowEnvInfo> GetEnvInfoAsync()
|
||||||
{
|
{
|
||||||
// 获取所有的程序集对应的方法信息(程序集相关的数据)
|
// 获取所有的程序集对应的方法信息(程序集相关的数据)
|
||||||
var libraryMdss = this.FlowLibraryService.GetAllLibraryMds().ToArray();
|
var libraryMdss = this._flowLibraryService.GetAllLibraryMds().ToArray();
|
||||||
// 获取当前项目的信息(节点相关的数据)
|
// 获取当前项目的信息(节点相关的数据)
|
||||||
var project = await GetProjectInfoAsync(); // 远程连接获取远程环境项目信息
|
var project = await GetProjectInfoAsync(); // 远程连接获取远程环境项目信息
|
||||||
SereinEnv.WriteLine(InfoType.INFO, "已将当前环境信息发送到远程客户端");
|
SereinEnv.WriteLine(InfoType.INFO, "已将当前环境信息发送到远程客户端");
|
||||||
@@ -328,8 +329,6 @@ namespace Serein.NodeFlow.Env
|
|||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
//
|
|
||||||
//await SetStartNodeAsync("", projectData.StartNode); // 设置起始节点
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,9 +427,9 @@ namespace Serein.NodeFlow.Env
|
|||||||
{
|
{
|
||||||
var projectData = new SereinProjectData()
|
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).ToArray(),
|
Nodes = _flowModelService.GetAllNodeModel().Select(node => node.ToInfo()).Where(info => info is not null).ToArray(),
|
||||||
Canvass = flowModelService.GetAllCanvasModel().Select(canvas => canvas.ToInfo()).ToArray(),
|
Canvass = _flowModelService.GetAllCanvasModel().Select(canvas => canvas.ToInfo()).ToArray(),
|
||||||
//StartNode = NodeModels.Values.FirstOrDefault(it => it.IsStart)?.Guid,
|
//StartNode = NodeModels.Values.FirstOrDefault(it => it.IsStart)?.Guid,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -445,24 +444,12 @@ namespace Serein.NodeFlow.Env
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public void LoadLibrary(string dllPath)
|
public void LoadLibrary(string dllPath)
|
||||||
{
|
{
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#region 检查是否已经加载本地依赖
|
var libraryInfo = _flowLibraryService.LoadFlowLibrary(dllPath);
|
||||||
var thisAssembly = typeof(IFlowEnvironment).Assembly;
|
if (libraryInfo is not null && libraryInfo.MethodInfos.Count > 0)
|
||||||
var thisAssemblyName = thisAssembly.GetName().Name;
|
|
||||||
if (!string.IsNullOrEmpty(thisAssemblyName) && FlowLibraryService.GetLibraryMdsOfAssmbly(thisAssemblyName).Count == 0)
|
|
||||||
{
|
{
|
||||||
var tmp = FlowLibraryService.LoadLibraryOfPath(thisAssembly.Location);
|
UIContextOperation?.Invoke(() => Event.OnDllLoad(new LoadDllEventArgs(libraryInfo))); // 通知UI创建dll面板显示
|
||||||
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面板显示
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -471,15 +458,15 @@ namespace Serein.NodeFlow.Env
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/* /// <summary>
|
||||||
/// 加载本地程序集
|
/// 加载本地程序集
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="flowLibrary"></param>
|
/// <param name="flowLibrary"></param>
|
||||||
public void LoadLibrary(FlowLibrary flowLibrary)
|
public void LoadLibrary(FlowLibraryCache flowLibrary)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
(var libraryInfo, var mdInfos) = FlowLibraryService.LoadLibraryOfPath(flowLibrary);
|
libraryInfo = FlowLibraryService.LoadFlowLibrary(flowLibrary);
|
||||||
if (mdInfos.Count > 0)
|
if (mdInfos.Count > 0)
|
||||||
{
|
{
|
||||||
UIContextOperation?.Invoke(() => Event.OnDllLoad(new LoadDllEventArgs(libraryInfo, mdInfos))); // 通知UI创建dll面板显示
|
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}");
|
SereinEnv.WriteLine(InfoType.ERROR, $"无法加载DLL文件:{ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -501,10 +488,10 @@ namespace Serein.NodeFlow.Env
|
|||||||
public bool TryUnloadLibrary(string assemblyName)
|
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)
|
if (groupedNodes.Length == 0)
|
||||||
{
|
{
|
||||||
var isPass = FlowLibraryService.UnloadLibrary(assemblyName);
|
var isPass = _flowLibraryService.UnloadLibrary(assemblyName);
|
||||||
return isPass;
|
return isPass;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -584,7 +571,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
{
|
{
|
||||||
var model = new FlowCanvasDetails(this);
|
var model = new FlowCanvasDetails(this);
|
||||||
model.LoadInfo(info);
|
model.LoadInfo(info);
|
||||||
flowModelService.AddCanvasModel(model);
|
_flowModelService.AddCanvasModel(model);
|
||||||
|
|
||||||
if(UIContextOperation is null)
|
if(UIContextOperation is null)
|
||||||
{
|
{
|
||||||
@@ -608,7 +595,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
|
|
||||||
public bool TryGetMethodDetailsInfo(string assemblyName, string methodName, out MethodDetailsInfo? mdInfo)
|
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)
|
if (!isPass || md is null)
|
||||||
{
|
{
|
||||||
mdInfo = null;
|
mdInfo = null;
|
||||||
@@ -633,7 +620,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails? delegateDetails)
|
public bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails? delegateDetails)
|
||||||
{
|
{
|
||||||
return FlowLibraryService.TryGetDelegateDetails(assemblyName, methodName, out delegateDetails);
|
return _flowLibraryService.TryGetDelegateDetails(assemblyName, methodName, out delegateDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -648,7 +635,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
}
|
}
|
||||||
this.UIContextOperation = uiContextOperation;
|
this.UIContextOperation = uiContextOperation;
|
||||||
IOC.Register<UIContextOperation>(() => uiContextOperation).Build();
|
IOC.Register<UIContextOperation>(() => uiContextOperation).Build();
|
||||||
|
OnUIContextOperationSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -713,9 +700,6 @@ namespace Serein.NodeFlow.Env
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从Guid获取画布
|
/// 从Guid获取画布
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -729,7 +713,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
canvasDetails = null;
|
canvasDetails = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return flowModelService.TryGetCanvasModel(nodeGuid, out canvasDetails);
|
return _flowModelService.TryGetCanvasModel(nodeGuid, out canvasDetails);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -746,7 +730,7 @@ namespace Serein.NodeFlow.Env
|
|||||||
nodeModel = null;
|
nodeModel = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return flowModelService.TryGetNodeModel(nodeGuid, out nodeModel);
|
return _flowModelService.TryGetNodeModel(nodeGuid, out nodeModel);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,6 +761,20 @@ namespace Serein.NodeFlow.Env
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置了 UIContextOperation 需要立刻执行的方法,用于加载基础库,创建第一个画布。
|
||||||
|
/// </summary>
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -97,9 +97,9 @@ namespace Serein.NodeFlow
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="libraryInfo"></param>
|
/// <param name="libraryInfo"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static NodeLibraryInfo ToLibrary(this NodeLibraryInfo libraryInfo)
|
public static FlowLibraryInfo ToLibrary(this FlowLibraryInfo libraryInfo)
|
||||||
{
|
{
|
||||||
return new NodeLibraryInfo
|
return new FlowLibraryInfo
|
||||||
{
|
{
|
||||||
AssemblyName = libraryInfo.AssemblyName,
|
AssemblyName = libraryInfo.AssemblyName,
|
||||||
FileName = libraryInfo.FileName,
|
FileName = libraryInfo.FileName,
|
||||||
|
|||||||
@@ -12,52 +12,52 @@ using System.Reflection;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加载在流程中的程序集依赖
|
/// 加载在流程中的程序集依赖
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class FlowLibrary
|
public class FlowLibraryCache
|
||||||
{
|
{
|
||||||
public Assembly Assembly { get; private set; }
|
/// <summary>
|
||||||
|
/// 通过程序集创建一个流程库实例
|
||||||
//private readonly Action actionOfUnloadAssmbly;
|
/// </summary>
|
||||||
/*, Action actionOfUnloadAssmbly*/
|
/// <param name="assembly"></param>
|
||||||
//this.actionOfUnloadAssmbly = actionOfUnloadAssmbly;
|
public FlowLibraryCache(Assembly assembly)
|
||||||
|
|
||||||
public FlowLibrary(Assembly assembly)
|
|
||||||
{
|
{
|
||||||
this.Assembly = assembly;
|
Assembly = assembly;
|
||||||
this.FullName = Path.GetFileName(Assembly.Location);
|
FullName = Path.GetFileName(Assembly.Location);
|
||||||
|
FilePath = Assembly.Location;
|
||||||
this.FilePath = Assembly.Location;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlowLibrary(Assembly assembly,
|
/// <summary>
|
||||||
|
/// 通过动态程序集和文件路径创建一个流程库实例
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dynamicAssembly"></param>
|
||||||
|
/// <param name="filePath"></param>
|
||||||
|
public FlowLibraryCache(Assembly dynamicAssembly,
|
||||||
string filePath)
|
string filePath)
|
||||||
{
|
{
|
||||||
this.Assembly = assembly;
|
Assembly = dynamicAssembly;
|
||||||
this.FullName = Path.GetFileName(filePath); ;
|
FullName = Path.GetFileName(filePath); ;
|
||||||
this.FilePath = filePath;
|
FilePath = filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 程序集本身
|
||||||
|
/// </summary>
|
||||||
|
public Assembly Assembly { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 程序集全名
|
||||||
|
/// </summary>
|
||||||
public string FullName { get; private set; }
|
public string FullName { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 程序集文件路径
|
||||||
|
/// </summary>
|
||||||
public string FilePath { get; private set; }
|
public string FilePath { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -65,60 +65,33 @@ namespace Serein.NodeFlow
|
|||||||
/// Key : 方法名称
|
/// Key : 方法名称
|
||||||
/// Value :方法详情
|
/// Value :方法详情
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ConcurrentDictionary<string, MethodDetails> MethodDetailss { get; } = new ConcurrentDictionary<string, MethodDetails>();
|
public Dictionary<string, MethodDetails> MethodDetailss { get; } = new Dictionary<string, MethodDetails>();
|
||||||
public ConcurrentDictionary<string, MethodInfo> MethodInfos { get; } = new ConcurrentDictionary<string, MethodInfo>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 管理通过Emit动态构建的委托
|
/// 加载程序集时创建的方法信息
|
||||||
/// Key :方法名称
|
|
||||||
/// Value :方法详情
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ConcurrentDictionary<string, DelegateDetails> DelegateDetailss { get; } = new ConcurrentDictionary<string, DelegateDetails>();
|
public Dictionary<string, MethodInfo> MethodInfos { get; } = new Dictionary<string, MethodInfo>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 记录不同的注册时机需要自动创建全局唯一实例的类型信息
|
/// <para>缓存节点方法通Emit委托</para>
|
||||||
|
/// <para>Key :方法名称</para>
|
||||||
|
/// <para>Value :方法详情</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ConcurrentDictionary<RegisterSequence, List<Type>> RegisterTypes { get; } = new ConcurrentDictionary<RegisterSequence, List<Type>>();
|
public Dictionary<string, DelegateDetails> DelegateDetailss { get; } = new Dictionary<string, DelegateDetails>();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 卸载当前程序集以及附带的所有信息
|
/// 用于流程启动时,在不同阶段(Init_Loading_Loaded)需要创建实例的类型信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Upload()
|
public Dictionary<RegisterSequence, List<Type>> RegisterTypes { get; } = new Dictionary<RegisterSequence, List<Type>>();
|
||||||
{
|
|
||||||
DelegateDetailss.Clear();
|
|
||||||
RegisterTypes.Clear();
|
|
||||||
MethodDetailss.Clear();
|
|
||||||
//actionOfUnloadAssmbly?.Invoke();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 转为依赖信息
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public NodeLibraryInfo ToInfo()
|
|
||||||
{
|
|
||||||
var assemblyName = Assembly.GetName().Name;
|
|
||||||
return new NodeLibraryInfo
|
|
||||||
{
|
|
||||||
AssemblyName = assemblyName,
|
|
||||||
FileName = this.FullName,
|
|
||||||
FilePath = this.FilePath,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 动态加载程序集
|
/// 动态加载程序集
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="assembly">程序集本身</param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool LoadAssembly()
|
public bool LoadFlowMethod()
|
||||||
{
|
{
|
||||||
Assembly assembly = this.Assembly;
|
Assembly assembly = Assembly;
|
||||||
|
|
||||||
#region 检查入参
|
#region 检查入参
|
||||||
|
|
||||||
@@ -132,7 +105,7 @@ namespace Serein.NodeFlow
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
types = assembly.GetTypes().ToList(); // 获取程序集中的所有类型
|
types = assembly.GetTypes().ToList(); // 获取程序集中的所有类型
|
||||||
if (types.Count < 0) // 防止动态程序集中没有类型信息?
|
if (types.Count <= 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -143,7 +116,7 @@ namespace Serein.NodeFlow
|
|||||||
var loaderExceptions = ex.LoaderExceptions;
|
var loaderExceptions = ex.LoaderExceptions;
|
||||||
foreach (var loaderException in loaderExceptions)
|
foreach (var loaderException in loaderExceptions)
|
||||||
{
|
{
|
||||||
SereinEnv.WriteLine(InfoType.ERROR, loaderException?.Message);
|
SereinEnv.WriteLine(InfoType.ERROR, "加载失败 : " + loaderException?.Message);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -160,8 +133,7 @@ namespace Serein.NodeFlow
|
|||||||
// Type : 具有 DynamicFlowAttribute 标记的类型
|
// Type : 具有 DynamicFlowAttribute 标记的类型
|
||||||
// string : 类型元数据 DynamicFlowAttribute 特性中的 Name 属性
|
// string : 类型元数据 DynamicFlowAttribute 特性中的 Name 属性
|
||||||
|
|
||||||
types = types.Where(type => type.GetCustomAttribute<DynamicFlowAttribute>() is DynamicFlowAttribute dynamicFlowAttribute
|
types = types.Where(type => type.GetCustomAttribute<DynamicFlowAttribute>() is DynamicFlowAttribute df && df.Scan).ToList();
|
||||||
&& dynamicFlowAttribute.Scan).ToList();
|
|
||||||
|
|
||||||
foreach (var type in types)
|
foreach (var type in types)
|
||||||
{
|
{
|
||||||
@@ -208,20 +180,16 @@ namespace Serein.NodeFlow
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 简单排序一下
|
|
||||||
//detailss = detailss.OrderBy(k => k.MethodDetails.MethodName,).ToList();
|
|
||||||
|
|
||||||
|
// 简单排序一下
|
||||||
|
|
||||||
detailss.Sort((a, b) => string.Compare(a.MethodDetails.MethodName, b.MethodDetails.MethodName, StringComparison.OrdinalIgnoreCase));
|
detailss.Sort((a, b) => string.Compare(a.MethodDetails.MethodName, b.MethodDetails.MethodName, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
foreach (var item in detailss)
|
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 加载成功,缓存所有方法、委托的信息
|
#region 加载成功,缓存所有方法、委托的信息
|
||||||
foreach (var item in detailss)
|
foreach (var item in detailss)
|
||||||
{
|
{
|
||||||
@@ -253,6 +221,36 @@ namespace Serein.NodeFlow
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 卸载当前程序集以及附带的所有信息
|
||||||
|
/// </summary>
|
||||||
|
public void Unload()
|
||||||
|
{
|
||||||
|
DelegateDetailss.Clear();
|
||||||
|
MethodInfos.Clear();
|
||||||
|
RegisterTypes.Clear();
|
||||||
|
MethodDetailss.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 转为依赖信息
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
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(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
20
NodeFlow/Model/Library/LibraryMdDd.cs
Normal file
20
NodeFlow/Model/Library/LibraryMdDd.cs
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -231,7 +231,7 @@ namespace Serein.NodeFlow.Model
|
|||||||
|
|
||||||
var returnType = sereinScript.ParserScript(Script, argTypes); // 开始解析获取程序主节点
|
var returnType = sereinScript.ParserScript(Script, argTypes); // 开始解析获取程序主节点
|
||||||
MethodDetails.ReturnType = returnType;
|
MethodDetails.ReturnType = returnType;
|
||||||
var scriptMethodInfo = sereinScript.ConvertCSharpCode(methodName, argTypes);
|
var scriptMethodInfo = sereinScript.ConvertCSharpCode(methodName, argTypes);
|
||||||
return scriptMethodInfo;
|
return scriptMethodInfo;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -42,18 +42,18 @@ namespace Serein.NodeFlow.Model.Operation
|
|||||||
{
|
{
|
||||||
if (!flowModelService.ContainsCanvasModel(CanvasGuid))
|
if (!flowModelService.ContainsCanvasModel(CanvasGuid))
|
||||||
{
|
{
|
||||||
flowEnvironment.WriteLine(Library.InfoType.INFO, $"节点取出失败,目标画布不存在[{NodeGuid}]");
|
flowEnvironment.WriteLine(Serein.Library.InfoType.WARN, $"节点取出失败,目标画布不存在[{NodeGuid}]");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 获取目标节点与容器节点
|
// 获取目标节点与容器节点
|
||||||
if (!flowModelService.TryGetNodeModel(NodeGuid, out var nodeModel))
|
if (!flowModelService.TryGetNodeModel(NodeGuid, out var nodeModel))
|
||||||
{
|
{
|
||||||
flowEnvironment.WriteLine(Library.InfoType.INFO, $"节点取出失败,目标节点不存在[{NodeGuid}]");
|
flowEnvironment.WriteLine(Serein.Library.InfoType.WARN, $"节点取出失败,目标节点不存在[{NodeGuid}]");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (nodeModel.ContainerNode is not INodeContainer containerNode)
|
if (nodeModel.ContainerNode is not INodeContainer containerNode)
|
||||||
{
|
{
|
||||||
flowEnvironment.WriteLine(Library.InfoType.INFO, $"节点取出失败,节点并非容器节点[{nodeModel.Guid}]");
|
flowEnvironment.WriteLine(Serein.Library.InfoType.WARN, $"节点取出失败,节点并非容器节点[{nodeModel.Guid}]");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Node = nodeModel;
|
Node = nodeModel;
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ namespace Serein.NodeFlow.Model.Operation
|
|||||||
|
|
||||||
// 节点与画布互相绑定
|
// 节点与画布互相绑定
|
||||||
nodeModel.CanvasDetails = flowCanvasDetails;
|
nodeModel.CanvasDetails = flowCanvasDetails;
|
||||||
flowCanvasDetails.Nodes.Add(nodeModel);
|
flowCanvasDetails.Nodes = [..flowCanvasDetails.Nodes, nodeModel];
|
||||||
|
|
||||||
flowModelService.AddNodeModel(nodeModel);
|
flowModelService.AddNodeModel(nodeModel);
|
||||||
this.flowNode = nodeModel;
|
this.flowNode = nodeModel;
|
||||||
|
|||||||
@@ -1,15 +1,5 @@
|
|||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Serein.Library;
|
||||||
using Serein.Library;
|
|
||||||
using Serein.Library.Api;
|
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
|
namespace Serein.NodeFlow.Model.Operation
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>1.2.1</Version>
|
<Version>1.2.2</Version>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
@@ -52,6 +52,7 @@
|
|||||||
<Compile Remove="Tool\Attribute.cs" />
|
<Compile Remove="Tool\Attribute.cs" />
|
||||||
<Compile Remove="Tool\DynamicTool.cs" />
|
<Compile Remove="Tool\DynamicTool.cs" />
|
||||||
<Compile Remove="Tool\ExpressionHelper.cs" />
|
<Compile Remove="Tool\ExpressionHelper.cs" />
|
||||||
|
<Compile Remove="Tool\FlowLibraryAssemblyContext2.cs" />
|
||||||
<Compile Remove="Tool\NodeModelBaseFunc.cs" />
|
<Compile Remove="Tool\NodeModelBaseFunc.cs" />
|
||||||
<Compile Remove="Tool\TcsSignal.cs" />
|
<Compile Remove="Tool\TcsSignal.cs" />
|
||||||
<Compile Remove="Tool\ToCSharpCodeHelper.cs" />
|
<Compile Remove="Tool\ToCSharpCodeHelper.cs" />
|
||||||
@@ -69,6 +70,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.13.0" />
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.6" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.6" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,14 @@
|
|||||||
using Serein.Library.Api;
|
using Serein.Library.Api;
|
||||||
using Serein.Library.FlowNode;
|
using Serein.Library.FlowNode;
|
||||||
using Serein.Library.Utils;
|
using Serein.Library.Utils;
|
||||||
|
using Serein.NodeFlow.Model.Library;
|
||||||
|
using Serein.NodeFlow.Tool;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.Loader;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
@@ -28,54 +29,95 @@ namespace Serein.NodeFlow.Services
|
|||||||
private readonly IFlowEnvironment flowEnvironment;
|
private readonly IFlowEnvironment flowEnvironment;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 缓存所有加载了的程序集
|
/// 缓存流程依赖
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ConcurrentDictionary<string, FlowLibrary> _myFlowLibrarys = new ConcurrentDictionary<string, FlowLibrary>();
|
private readonly ConcurrentDictionary<string, FlowLibraryCache> _flowLibraryCaches = new ConcurrentDictionary<string, FlowLibraryCache>();
|
||||||
|
|
||||||
|
|
||||||
|
private readonly ConcurrentDictionary<string, FlowLibraryAssemblyContext> _flowLibraryAssemblyContexts
|
||||||
|
= new ConcurrentDictionary<string, FlowLibraryAssemblyContext>();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加载类库
|
/// 每个类库下面至少需要有“Serein.Library.dll”类库依赖
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="libraryfilePath"></param>
|
/// <param name="libraryfilePath"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public (NodeLibraryInfo, List<MethodDetailsInfo>) LoadLibraryOfPath(string libraryfilePath)
|
private bool CheckBaseLibrary(string libraryfilePath, out string baseLibraryPath)
|
||||||
{
|
{
|
||||||
|
|
||||||
var dir = Path.GetDirectoryName(libraryfilePath); // 获取目录路径
|
var dir = Path.GetDirectoryName(libraryfilePath); // 获取目录路径
|
||||||
var sereinFlowBaseLibraryPath = Path.Combine(dir, SereinBaseLibrary);// 每个类库下面至少需要有“Serein.Library.dll”类库依赖
|
var sereinFlowBaseLibraryPath = Path.Combine(dir, SereinBaseLibrary);
|
||||||
if (!Path.Exists(sereinFlowBaseLibraryPath))
|
if (!Path.Exists(sereinFlowBaseLibraryPath))
|
||||||
{
|
{
|
||||||
throw new Exception($"从文件加载DLL失败,目标文件夹不存在{SereinBaseLibrary}文件" );
|
baseLibraryPath = string.Empty;
|
||||||
}
|
return false;
|
||||||
|
|
||||||
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 = sereinFlowBaseLibraryPath;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加载类库
|
/// 加载基础依赖
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="flowLibrary"></param>
|
public FlowLibraryInfo LoadBaseLibrary()
|
||||||
/// <returns></returns>
|
|
||||||
public (NodeLibraryInfo, List<MethodDetailsInfo>) LoadLibraryOfPath(FlowLibrary flowLibrary)
|
|
||||||
{
|
{
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载流程依赖
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="libraryfilePath"></param>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 卸载类库
|
/// 卸载类库
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -83,11 +125,11 @@ namespace Serein.NodeFlow.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool UnloadLibrary(string assemblyName)
|
public bool UnloadLibrary(string assemblyName)
|
||||||
{
|
{
|
||||||
if (_myFlowLibrarys.Remove(assemblyName, out var flowLibrary))
|
if (_flowLibraryCaches.Remove(assemblyName, out var flowLibrary))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
flowLibrary.Upload(); // 尝试卸载
|
flowLibrary.Unload(); // 尝试卸载
|
||||||
flowLibrary = null;
|
flowLibrary = null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -104,6 +146,8 @@ namespace Serein.NodeFlow.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region 获取流程依赖的相关方法
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取方法描述
|
/// 获取方法描述
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -118,7 +162,7 @@ namespace Serein.NodeFlow.Services
|
|||||||
methodInfo = null;
|
methodInfo = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (_myFlowLibrarys.TryGetValue(assemblyName, out var flowLibrary)
|
if (_flowLibraryCaches.TryGetValue(assemblyName, out var flowLibrary)
|
||||||
&& flowLibrary.MethodInfos.TryGetValue(methodName, out methodInfo))
|
&& flowLibrary.MethodInfos.TryGetValue(methodName, out methodInfo))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@@ -130,7 +174,7 @@ namespace Serein.NodeFlow.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取方法描述
|
/// 获取方法描述
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="assemblyName">程序集名称</param>
|
/// <param name="assemblyName">程序集名称</param>
|
||||||
@@ -139,7 +183,7 @@ namespace Serein.NodeFlow.Services
|
|||||||
/// <returns>是否获取成功</returns>
|
/// <returns>是否获取成功</returns>
|
||||||
public bool TryGetMethodDetails(string assemblyName, string methodName, [MaybeNullWhen(false)] out MethodDetails md)
|
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))
|
&& flowLibrary.MethodDetailss.TryGetValue(methodName, out md))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@@ -160,7 +204,7 @@ namespace Serein.NodeFlow.Services
|
|||||||
/// <returns>是否获取成功</returns>
|
/// <returns>是否获取成功</returns>
|
||||||
public bool TryGetDelegateDetails(string assemblyName, string methodName, [MaybeNullWhen(false)] out DelegateDetails dd)
|
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))
|
&& flowLibrary.DelegateDetailss.TryGetValue(methodName, out dd))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@@ -182,7 +226,7 @@ namespace Serein.NodeFlow.Services
|
|||||||
{
|
{
|
||||||
List<MethodDetails> mds = [];
|
List<MethodDetails> 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();
|
var t_mds = library.MethodDetailss.Values.Where(it => it.MethodDynamicType == nodeType).ToList();
|
||||||
mds.AddRange(t_mds);
|
mds.AddRange(t_mds);
|
||||||
@@ -197,7 +241,7 @@ namespace Serein.NodeFlow.Services
|
|||||||
public Dictionary<RegisterSequence, List<Type>> GetaAutoRegisterType()
|
public Dictionary<RegisterSequence, List<Type>> GetaAutoRegisterType()
|
||||||
{
|
{
|
||||||
Dictionary<RegisterSequence, List<Type>> rsTypes = new Dictionary<RegisterSequence, List<Type>>();
|
Dictionary<RegisterSequence, List<Type>> rsTypes = new Dictionary<RegisterSequence, List<Type>>();
|
||||||
foreach (var library in _myFlowLibrarys.Values)
|
foreach (var library in _flowLibraryCaches.Values)
|
||||||
{
|
{
|
||||||
foreach (var kv in library.RegisterTypes)
|
foreach (var kv in library.RegisterTypes)
|
||||||
{
|
{
|
||||||
@@ -220,28 +264,26 @@ namespace Serein.NodeFlow.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public List<MethodDetails> GetLibraryMdsOfAssmbly(string assemblyName)
|
public List<MethodDetails> GetLibraryMdsOfAssmbly(string assemblyName)
|
||||||
{
|
{
|
||||||
if (_myFlowLibrarys.TryGetValue(assemblyName, out var flowLibrary))
|
if (_flowLibraryCaches.TryGetValue(assemblyName, out var flowLibrary))
|
||||||
{
|
{
|
||||||
return flowLibrary.MethodDetailss.Values.ToList();
|
return flowLibrary.MethodDetailss.Values.ToList();
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取所有方法信息,用于保存项目时调用
|
/// 获取流程方法信息,用于保存项目时调用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public List<LibraryMds> GetAllLibraryMds()
|
public List<FlowLibraryInfo> GetAllLibraryMds()
|
||||||
{
|
{
|
||||||
List<LibraryMds> mds = new List<LibraryMds>();
|
List<FlowLibraryInfo> mds = new List<FlowLibraryInfo>();
|
||||||
foreach (FlowLibrary library in _myFlowLibrarys.Values)
|
foreach (FlowLibraryCache library in _flowLibraryCaches.Values)
|
||||||
{
|
{
|
||||||
var tmp = new LibraryMds
|
var tmp = new FlowLibraryInfo
|
||||||
{
|
{
|
||||||
AssemblyName = library.FullName,
|
AssemblyName = library.FullName,
|
||||||
Mds = library.MethodDetailss.Values.Select(md => md.ToInfo()).ToArray()
|
MethodInfos = library.MethodDetailss.Values.Select(md => md.ToInfo()).ToList()
|
||||||
};
|
};
|
||||||
mds.Add(tmp);
|
mds.Add(tmp);
|
||||||
}
|
}
|
||||||
@@ -253,11 +295,11 @@ namespace Serein.NodeFlow.Services
|
|||||||
/// 序列化当前项目的依赖信息、节点信息,用于远程登录的场景,需要将依赖信息从本地(受控端)发送到远程(主控端)
|
/// 序列化当前项目的依赖信息、节点信息,用于远程登录的场景,需要将依赖信息从本地(受控端)发送到远程(主控端)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public List<NodeLibraryInfo> GetAllLibraryInfo()
|
public List<FlowLibraryInfo> GetAllLibraryInfo()
|
||||||
{
|
{
|
||||||
return _myFlowLibrarys.Values.Select(library => library.ToInfo()).ToList();
|
return _flowLibraryCaches.Values.Select(library => library.ToInfo()).ToList();
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region 功能性方法
|
#region 功能性方法
|
||||||
|
|
||||||
@@ -266,132 +308,7 @@ namespace Serein.NodeFlow.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static string SereinBaseLibrary = $"{nameof(Serein)}.{nameof(Library)}.dll";
|
public readonly static string SereinBaseLibrary = $"{nameof(Serein)}.{nameof(Library)}.dll";
|
||||||
|
|
||||||
//private (NodeLibraryInfo, List<MethodDetailsInfo>) 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<MethodDetailsInfo>) 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<MethodDetailsInfo> mdInfos = flowLibrary.MethodDetailss.Values.Select(md => md.ToInfo()).ToList();
|
|
||||||
mdInfos.Sort((a, b) => string.Compare(a.MethodName, b.MethodName, StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
(NodeLibraryInfo, List<MethodDetailsInfo>) result = (flowLibrary.ToInfo(), mdInfos);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception($"程序集[{assembly.GetName().FullName}]加载失败");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 流程依赖加载
|
|
||||||
/// </summary>
|
|
||||||
public class FlowLibraryAssemblyContext : AssemblyLoadContext
|
|
||||||
{
|
|
||||||
private readonly AssemblyDependencyResolver _resolver;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 创建新的加载上下文
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sereinFlowLibraryPath">类库路径</param>
|
|
||||||
/// <param name="name"></param>
|
|
||||||
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);
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.CSharp;
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
using Microsoft.CodeAnalysis.Emit;
|
using Microsoft.CodeAnalysis.Emit;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Serein.NodeFlow.Tool
|
namespace Serein.NodeFlow.Tool
|
||||||
{
|
{
|
||||||
|
|||||||
59
NodeFlow/Tool/FlowLibraryAssemblyContext.cs
Normal file
59
NodeFlow/Tool/FlowLibraryAssemblyContext.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Loader;
|
||||||
|
|
||||||
|
namespace Serein.NodeFlow.Tool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 流程依赖加载
|
||||||
|
/// </summary>
|
||||||
|
public class FlowLibraryAssemblyContext : AssemblyLoadContext
|
||||||
|
{
|
||||||
|
private readonly AssemblyDependencyResolver _resolver;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建新的加载上下文
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="baseLibraryPath">流程基础依赖类库路径</param>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
public FlowLibraryAssemblyContext(string baseLibraryPath, string name) : base(name, isCollectible: true)
|
||||||
|
{
|
||||||
|
_resolver = new AssemblyDependencyResolver(baseLibraryPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载指定的程序集
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="assemblyName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
NodeFlow/Tool/FlowLibraryAssemblyContext2.cs
Normal file
44
NodeFlow/Tool/FlowLibraryAssemblyContext2.cs
Normal file
@@ -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
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 流程依赖加载
|
||||||
|
/// </summary>
|
||||||
|
public class FlowLibraryAssemblyContext : AssemblyLoadContext
|
||||||
|
{
|
||||||
|
private readonly AssemblyDependencyResolver _resolver;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建新的加载上下文
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sereinFlowLibraryPath">类库路径</param>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,4 @@
|
|||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Serein.Library.Utils;
|
||||||
using Serein.Library.Utils;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Serein.Extend.NewtonsoftJson
|
namespace Serein.Extend.NewtonsoftJson
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,15 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<BaseOutputPath>..\.\.Output</BaseOutputPath>
|
||||||
|
|
||||||
|
<Title>为 SereinFlow 提供的 JSON 扩展</Title>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<Description>通过 NewtonsoftJson 实现JSON门户扩展,用于解决 Serein.Proto.* 项目下需要 JSON 序列化与反序列化的场景</Description>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||||
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" PrivateAssets="all" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!--<ItemGroup>
|
<!--<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0">
|
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0">
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ namespace Serein.Proto.Modbus
|
|||||||
/// 创建 Modbus 客户端实例
|
/// 创建 Modbus 客户端实例
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="connectionString">
|
/// <param name="connectionString">
|
||||||
/// 连接字符串格式:
|
/// <para>连接字符串格式: </para>
|
||||||
/// TCP示例:"tcp:192.168.1.100:502"
|
/// <para>TCP示例:"tcp:192.168.1.100:502" </para>
|
||||||
/// UCP示例:"ucp:192.168.1.100:502"
|
/// <para>UCP示例:"ucp:192.168.1.100:502" </para>
|
||||||
/// RTU示例:"rtu:COM3:9600:1" (格式:rtu:串口名:波特率:从站地址)
|
/// <para>RTU示例:"rtu:COM3:9600:1" (格式:rtu:串口名:波特率:从站地址) </para>
|
||||||
/// </param>
|
/// </param>
|
||||||
public static IModbusClient Create(string connectionString)
|
public static IModbusClient Create(string connectionString)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,15 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<BaseOutputPath>..\.\.Output</BaseOutputPath>
|
||||||
|
|
||||||
|
<Title>全异步Modbus协议客户端工具包</Title>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<Description>提供TCP、UDP、RTU三种方式客户端;创建方式:IModbusClient client = ModbusClientFactory.Create...;</Description>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||||
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -5,6 +5,15 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<BaseOutputPath>..\.\.Output</BaseOutputPath>
|
||||||
|
|
||||||
|
<Title>基于Json数据载体的WebSocket交互工具包</Title>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<Description>基于Json数据载体的WebSocket交互工具包</Description>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||||
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,13 +1,4 @@
|
|||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
namespace Serein.Script
|
||||||
using Serein.Library.Api;
|
|
||||||
using Serein.Script.Node;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Serein.Script
|
|
||||||
{
|
{
|
||||||
internal static class NodeInterpreterExtension
|
internal static class NodeInterpreterExtension
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,15 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<BaseOutputPath>..\.\.Output</BaseOutputPath>
|
<BaseOutputPath>..\.\.Output</BaseOutputPath>
|
||||||
|
|
||||||
|
<Title>基于AST实现的脚本语言</Title>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<Description>使用了Emit构造委托缓存调用,性能客观。提供了类型推导、转换C#代码功能。用于流程图中脚本处理,也可在其他地方进行使用。</Description>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
|
<RepositoryUrl>https://github.com/fhhyyp/serein-flow</RepositoryUrl>
|
||||||
|
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||||
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -18,7 +27,16 @@
|
|||||||
<None Remove="TestExpression\**" />
|
<None Remove="TestExpression\**" />
|
||||||
<None Remove="Tool\**" />
|
<None Remove="Tool\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\LICENSE">
|
||||||
|
<Pack>True</Pack>
|
||||||
|
<PackagePath>\</PackagePath>
|
||||||
|
</None>
|
||||||
|
<None Include="..\README.md">
|
||||||
|
<Pack>True</Pack>
|
||||||
|
<PackagePath>\</PackagePath>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Remove="Node\ExpressionNode.cs" />
|
<Compile Remove="Node\ExpressionNode.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,14 +1,7 @@
|
|||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Serein.Library;
|
||||||
using Serein.Library;
|
|
||||||
using Serein.Library.Api;
|
|
||||||
using Serein.Script.Node;
|
using Serein.Script.Node;
|
||||||
using Serein.Script.Node.FlowControl;
|
using Serein.Script.Node.FlowControl;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Serein.Script
|
namespace Serein.Script
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -269,9 +269,8 @@ namespace Serein.Script
|
|||||||
}
|
}
|
||||||
ASTNode tempNode = peekToken3.Type switch
|
ASTNode tempNode = peekToken3.Type switch
|
||||||
{
|
{
|
||||||
TokenType.Dot => ParseMemberAccessNode(source), // 获取对象中的成员 source.Value...
|
TokenType.Dot or TokenType.Semicolon or TokenType.ParenthesisRight =>
|
||||||
TokenType.Semicolon => ParseMemberAccessNode(source), // 获取对象中的成员 source.Value...
|
ParseMemberAccessNode(source), // 获取对象中的成员 source.Value...
|
||||||
TokenType.ParenthesisRight => ParseMemberAccessNode(source), // 获取对象中的成员 source.Value...
|
|
||||||
TokenType.SquareBracketsLeft => ParseCollectionIndexNode(source), // 获取集合中的元素 source[index]....
|
TokenType.SquareBracketsLeft => ParseCollectionIndexNode(source), // 获取集合中的元素 source[index]....
|
||||||
TokenType.ParenthesisLeft => ParseMemberFunctionCallNode(source), // 获取需要调用的方法 source(arg1,arg2...)...
|
TokenType.ParenthesisLeft => ParseMemberFunctionCallNode(source), // 获取需要调用的方法 source(arg1,arg2...)...
|
||||||
_ => throw new Exception($"无法从对象获取成员,当前Token类型为 {peekToken.Type}。")
|
_ => throw new Exception($"无法从对象获取成员,当前Token类型为 {peekToken.Type}。")
|
||||||
@@ -963,11 +962,9 @@ namespace Serein.Script
|
|||||||
var peekToken3 = _lexer.PeekToken();
|
var peekToken3 = _lexer.PeekToken();
|
||||||
ASTNode tempNode = peekToken3.Type switch
|
ASTNode tempNode = peekToken3.Type switch
|
||||||
{
|
{
|
||||||
TokenType.Comma => ParseMemberAccessNode(source), // 获取对象中的成员 source.Value...
|
TokenType.Comma or TokenType.Operator or TokenType.Dot or TokenType.Semicolon or TokenType.ParenthesisRight
|
||||||
TokenType.Operator => ParseMemberAccessNode(source), // 获取对象中的成员 source.Value...
|
=> ParseMemberAccessNode(source), // 获取对象中的成员 source.Value...
|
||||||
TokenType.Dot => ParseMemberAccessNode(source), // 获取对象中的成员 source.Value...
|
|
||||||
TokenType.Semicolon => ParseMemberAccessNode(source), // 获取对象中的成员 source.Value...
|
|
||||||
TokenType.ParenthesisRight => ParseMemberAccessNode(source), // 获取对象中的成员 source.Value...
|
|
||||||
TokenType.SquareBracketsLeft => ParseCollectionIndexNode(source), // 获取集合中的元素 source[index]....
|
TokenType.SquareBracketsLeft => ParseCollectionIndexNode(source), // 获取集合中的元素 source[index]....
|
||||||
TokenType.ParenthesisLeft => ParseMemberFunctionCallNode(source), // 获取需要调用的方法 source(arg1,arg2...)...
|
TokenType.ParenthesisLeft => ParseMemberFunctionCallNode(source), // 获取需要调用的方法 source(arg1,arg2...)...
|
||||||
_ => throw new Exception($"无法从对象获取成员,当前Token : {peekToken.ToString()}。")
|
_ => throw new Exception($"无法从对象获取成员,当前Token : {peekToken.ToString()}。")
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Serein.Library;
|
||||||
using Serein.Library;
|
|
||||||
using Serein.Library.Api;
|
|
||||||
using Serein.Workbench.Api;
|
using Serein.Workbench.Api;
|
||||||
using Serein.Workbench.Node.ViewModel;
|
using Serein.Workbench.Node.ViewModel;
|
||||||
using Serein.Workbench.Themes;
|
using Serein.Workbench.Themes;
|
||||||
using Serein.Workbench.Views;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
using System.Windows.Input;
|
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
|
||||||
namespace Serein.Workbench.Node.View
|
namespace Serein.Workbench.Node.View
|
||||||
|
|||||||
@@ -1,14 +1,6 @@
|
|||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Serein.NodeFlow.Model;
|
||||||
using Serein.Library;
|
using Serein.NodeFlow.Model.Library;
|
||||||
using Serein.NodeFlow;
|
|
||||||
using Serein.NodeFlow.Model;
|
|
||||||
using Serein.Workbench.Themes;
|
using Serein.Workbench.Themes;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Documents;
|
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
|
||||||
namespace Serein.Workbench.Node.ViewModel
|
namespace Serein.Workbench.Node.ViewModel
|
||||||
@@ -71,9 +63,9 @@ public class FlowLibrary
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnCompileComplete(FlowLibrary flowLibrary)
|
private static void OnCompileComplete(FlowLibraryCache flowLibrary)
|
||||||
{
|
{
|
||||||
var loadResult = flowLibrary.LoadAssembly(); // 动态编译完成后加载程序集
|
var loadResult = flowLibrary.LoadFlowMethod(); // 动态编译完成后加载程序集
|
||||||
if (!loadResult)
|
if (!loadResult)
|
||||||
{
|
{
|
||||||
return ;
|
return ;
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ namespace Serein.Workbench.Services
|
|||||||
SereinEnv.WriteLine(InfoType.INFO, "项目文件保存路径:" + savePath);
|
SereinEnv.WriteLine(InfoType.INFO, "项目文件保存路径:" + savePath);
|
||||||
for (int index = 0; index < project.Librarys.Length; index++)
|
for (int index = 0; index < project.Librarys.Length; index++)
|
||||||
{
|
{
|
||||||
NodeLibraryInfo? library = project.Librarys[index];
|
FlowLibraryInfo? library = project.Librarys[index];
|
||||||
string sourceFilePath = new Uri(library.FilePath).LocalPath; // 源文件夹
|
string sourceFilePath = new Uri(library.FilePath).LocalPath; // 源文件夹
|
||||||
string targetDir = System.IO.Path.Combine(librarySavePath, library.AssemblyName); // 目标文件夹
|
string targetDir = System.IO.Path.Combine(librarySavePath, library.AssemblyName); // 目标文件夹
|
||||||
if (!Path.Exists(targetDir))
|
if (!Path.Exists(targetDir))
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using Serein.NodeFlow;
|
using Serein.NodeFlow.Model.Library;
|
||||||
using Serein.NodeFlow.Tool;
|
using Serein.NodeFlow.Tool;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -34,7 +34,7 @@ namespace Serein.Workbench.Themes
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 编译成功回调
|
/// 编译成功回调
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Action<FlowLibrary> OnCompileComplete { get; set; }
|
public Action<FlowLibraryCache> OnCompileComplete { get; set; }
|
||||||
public DynamicCompilerView()
|
public DynamicCompilerView()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@@ -132,7 +132,7 @@ namespace Serein.Workbench.Themes
|
|||||||
var path = textboxAssemblyName.Text;
|
var path = textboxAssemblyName.Text;
|
||||||
Assembly assembly = _compiler.Compile(code, path);
|
Assembly assembly = _compiler.Compile(code, path);
|
||||||
|
|
||||||
FlowLibrary flowLibrary = new FlowLibrary(assembly, path);
|
FlowLibraryCache flowLibrary = new FlowLibraryCache(assembly, path);
|
||||||
|
|
||||||
if (assembly != null)
|
if (assembly != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ namespace Serein.Workbench.ViewModels
|
|||||||
private readonly IFlowEEForwardingService flowEEForwardingService;
|
private readonly IFlowEEForwardingService flowEEForwardingService;
|
||||||
private readonly IFlowEnvironment flowEnvironment;
|
private readonly IFlowEnvironment flowEnvironment;
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private ObservableCollection<FlowLibraryInfo> flowLibraryInfos;
|
private ObservableCollection<Models.FlowLibraryInfo> flowLibraryInfos;
|
||||||
|
|
||||||
public FlowLibrarysViewModel(IFlowEEForwardingService flowEEForwardingService,IFlowEnvironment flowEnvironment)
|
public FlowLibrarysViewModel(IFlowEEForwardingService flowEEForwardingService,IFlowEnvironment flowEnvironment)
|
||||||
{
|
{
|
||||||
this.flowEEForwardingService = flowEEForwardingService;
|
this.flowEEForwardingService = flowEEForwardingService;
|
||||||
this.flowEnvironment = flowEnvironment;
|
this.flowEnvironment = flowEnvironment;
|
||||||
FlowLibraryInfos = new ObservableCollection<FlowLibraryInfo>();
|
FlowLibraryInfos = new ObservableCollection<Models.FlowLibraryInfo>();
|
||||||
flowEEForwardingService.DllLoad += FlowEEForwardingService_OnDllLoad;
|
flowEEForwardingService.DllLoad += FlowEEForwardingService_OnDllLoad;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -48,15 +48,15 @@ namespace Serein.Workbench.ViewModels
|
|||||||
private void FlowEEForwardingService_OnDllLoad(Library.Api.LoadDllEventArgs eventArgs)
|
private void FlowEEForwardingService_OnDllLoad(Library.Api.LoadDllEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (!eventArgs.IsSucceed) return;
|
if (!eventArgs.IsSucceed) return;
|
||||||
List<MethodDetailsInfo> mds = eventArgs.MethodDetailss;
|
List<MethodDetailsInfo> mds = eventArgs.NodeLibraryInfo.MethodInfos.ToList() ;
|
||||||
NodeLibraryInfo libraryInfo = eventArgs.NodeLibraryInfo;
|
Library.FlowLibraryInfo libraryInfo = eventArgs.NodeLibraryInfo;
|
||||||
|
|
||||||
var methodInfo = new ObservableCollection<MethodDetailsInfo>();
|
var methodInfo = new ObservableCollection<MethodDetailsInfo>();
|
||||||
foreach (var md in mds)
|
foreach (var md in mds)
|
||||||
{
|
{
|
||||||
methodInfo.Add(md);
|
methodInfo.Add(md);
|
||||||
}
|
}
|
||||||
var flInfo = new FlowLibraryInfo
|
var flInfo = new Models.FlowLibraryInfo
|
||||||
{
|
{
|
||||||
LibraryName = libraryInfo.AssemblyName,
|
LibraryName = libraryInfo.AssemblyName,
|
||||||
FilePath = libraryInfo.FilePath,
|
FilePath = libraryInfo.FilePath,
|
||||||
|
|||||||
Reference in New Issue
Block a user