mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-19 16:06:33 +08:00
重新设计了项目的保存文件结构
This commit is contained in:
@@ -5,6 +5,7 @@ using Serein.Library.Utils.SereinExpression;
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.NodeFlow.Tool;
|
||||
using System.Reactive;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Serein.NodeFlow.Env
|
||||
@@ -52,6 +53,7 @@ namespace Serein.NodeFlow.Env
|
||||
NodeMVVMManagement.RegisterModel(NodeControlType.ConditionRegion, typeof(CompositeConditionNode)); // 条件区域
|
||||
NodeMVVMManagement.RegisterModel(NodeControlType.GlobalData, typeof(SingleGlobalDataNode)); // 全局数据节点
|
||||
NodeMVVMManagement.RegisterModel(NodeControlType.Script, typeof(SingleScriptNode)); // 脚本节点
|
||||
NodeMVVMManagement.RegisterModel(NodeControlType.NetScript, typeof(SingleNetScriptNode)); // 脚本节点
|
||||
#endregion
|
||||
|
||||
#region 注册基本服务类
|
||||
@@ -647,9 +649,30 @@ namespace Serein.NodeFlow.Env
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"无法加载DLL文件:{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载本地程序集
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
public void LoadLibrary(Assembly assembly)
|
||||
{
|
||||
try
|
||||
{
|
||||
(var libraryInfo, var mdInfos) = FlowLibraryManagement.LoadLibraryOfPath(assembly);
|
||||
if (mdInfos.Count > 0)
|
||||
{
|
||||
UIContextOperation?.Invoke(() => OnDllLoad?.Invoke(new LoadDllEventArgs(libraryInfo, mdInfos))); // 通知UI创建dll面板显示
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"无法加载DLL文件:{ex}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 移除DLL
|
||||
/// </summary>
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace Serein.NodeFlow
|
||||
|
||||
flipflopNodes = nodes.Where(it => it.MethodDetails?.MethodDynamicType == NodeType.Flipflop && it.IsStart == false)
|
||||
.Select(it => (SingleFlipflopNode)it)
|
||||
.Where(node => node is SingleFlipflopNode flipflopNode && flipflopNode.NotExitPreviousNode())
|
||||
.Where(node => node.DebugSetting.IsEnable && node is SingleFlipflopNode flipflopNode && flipflopNode.NotExitPreviousNode())
|
||||
.ToList();// 获取需要再运行开始之前启动的触发器节点
|
||||
runNodeMd = nodes.Select(item => item.MethodDetails).ToList(); // 获取环境中所有节点的方法信息
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Serein.NodeFlow.Model
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Expression Operation - 表达式操作
|
||||
/// </summary>
|
||||
[NodeProperty(ValuePath = NodeValuePath.Node)]
|
||||
@@ -51,7 +51,11 @@ namespace Serein.NodeFlow.Model
|
||||
/// </summary>
|
||||
private NodeModelBase? DataNode;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 有节点被放置
|
||||
/// </summary>
|
||||
/// <param name="nodeModel"></param>
|
||||
/// <returns></returns>
|
||||
public bool PlaceNode(NodeModelBase nodeModel)
|
||||
{
|
||||
if(DataNode is null)
|
||||
|
||||
122
NodeFlow/Model/SingleNetScriptNode.cs
Normal file
122
NodeFlow/Model/SingleNetScriptNode.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using Serein.Library;
|
||||
using Serein.Library.Api;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.NodeFlow.Model
|
||||
{
|
||||
|
||||
[NodeProperty(ValuePath = NodeValuePath.Node)]
|
||||
public partial class SingleNetScriptNode : NodeModelBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 脚本代码
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private string _script;
|
||||
|
||||
/// <summary>
|
||||
/// 功能提示
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private string _tips = "写一下提示吧";
|
||||
|
||||
/// <summary>
|
||||
/// 依赖路径
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private List<string> _libraryFilePaths;
|
||||
|
||||
}
|
||||
|
||||
public partial class SingleNetScriptNode
|
||||
{
|
||||
/// <summary>
|
||||
/// 表达式节点是基础节点
|
||||
/// </summary>
|
||||
public override bool IsBase => true;
|
||||
|
||||
public SingleNetScriptNode(IFlowEnvironment environment) : base(environment)
|
||||
{
|
||||
this.Env = environment;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public override void OnCreating()
|
||||
{
|
||||
//MethodInfo? method = this.GetType().GetMethod(nameof(GetFlowApi));
|
||||
//if (method != null)
|
||||
//{
|
||||
// ScriptInterpreter.AddFunction(nameof(GetFlowApi), method, () => this); // 挂载获取流程接口
|
||||
//}
|
||||
|
||||
//var md = MethodDetails;
|
||||
//var pd = md.ParameterDetailss ??= new ParameterDetails[1];
|
||||
//md.ParamsArgIndex = 0;
|
||||
//pd[0] = new ParameterDetails
|
||||
//{
|
||||
// Index = 0,
|
||||
// Name = "object",
|
||||
// IsExplicitData = true,
|
||||
// DataValue = string.Empty,
|
||||
// DataType = typeof(object),
|
||||
// ExplicitType = typeof(object),
|
||||
// ArgDataSourceNodeGuid = string.Empty,
|
||||
// ArgDataSourceType = ConnectionArgSourceType.GetPreviousNodeData,
|
||||
// NodeModel = this,
|
||||
// InputType = ParameterValueInputType.Input,
|
||||
// Items = null,
|
||||
// IsParams = true,
|
||||
// Description = "脚本节点入参"
|
||||
|
||||
//};
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出脚本代码
|
||||
/// </summary>
|
||||
/// <param name="nodeInfo"></param>
|
||||
/// <returns></returns>
|
||||
public override NodeInfo SaveCustomData(NodeInfo nodeInfo)
|
||||
{
|
||||
dynamic data = new ExpandoObject();
|
||||
data.Script = this.Script ?? "";
|
||||
nodeInfo.CustomData = data;
|
||||
return nodeInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载自定义数据
|
||||
/// </summary>
|
||||
/// <param name="nodeInfo"></param>
|
||||
public override void LoadCustomData(NodeInfo nodeInfo)
|
||||
{
|
||||
this.Script = nodeInfo.CustomData?.Script ?? "";
|
||||
|
||||
// 更新变量名
|
||||
//for (int i = 0; i < Math.Min(this.MethodDetails.ParameterDetailss.Length, nodeInfo.ParameterData.Length); i++)
|
||||
//{
|
||||
// this.MethodDetails.ParameterDetailss[i].Name = nodeInfo.ParameterData[i].ArgName;
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -28,13 +28,11 @@ namespace Serein.NodeFlow.Model
|
||||
/// </summary>
|
||||
public partial class SingleScriptNode : NodeModelBase
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 脚本节点是基础节点
|
||||
/// </summary>
|
||||
public override bool IsBase => true;
|
||||
|
||||
|
||||
private IScriptFlowApi ScriptFlowApi { get; }
|
||||
|
||||
private ASTNode mainNode;
|
||||
|
||||
127
NodeFlow/Tool/DynamicCompiler.cs
Normal file
127
NodeFlow/Tool/DynamicCompiler.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// 动态编译
|
||||
/// </summary>
|
||||
public class DynamicCompiler
|
||||
{
|
||||
private readonly HashSet<MetadataReference> _references = new HashSet<MetadataReference>();
|
||||
|
||||
public DynamicCompiler()
|
||||
{
|
||||
// 默认添加当前 AppDomain 加载的所有程序集
|
||||
var defaultReferences = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.Where(a => !string.IsNullOrEmpty(a.Location)) // a.IsDynamic 动态程序集
|
||||
.Select(a => MetadataReference.CreateFromFile(a.Location));
|
||||
|
||||
|
||||
//AddReference(this.GetType());
|
||||
_references.UnionWith(defaultReferences);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加依赖程序集(通过类型)
|
||||
/// </summary>
|
||||
/// <param name="type">类型所在的程序集</param>
|
||||
public void AddReference(Type type)
|
||||
{
|
||||
var assemblyLocation = type.Assembly.Location;
|
||||
if (!string.IsNullOrEmpty(assemblyLocation))
|
||||
{
|
||||
_references.Add(MetadataReference.CreateFromFile(assemblyLocation));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加依赖程序集(通过文件路径)
|
||||
/// </summary>
|
||||
/// <param name="assemblyPath">程序集文件路径</param>
|
||||
public void AddReference(string assemblyPath)
|
||||
{
|
||||
if (File.Exists(assemblyPath))
|
||||
{
|
||||
_references.Add(MetadataReference.CreateFromFile(assemblyPath));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 编译 C# 代码并返回程序集
|
||||
/// </summary>
|
||||
/// <param name="code">C# 代码文本</param>
|
||||
/// <param name="assemblyName">程序集名称(可选)</param>
|
||||
/// <returns>成功返回 Assembly,失败返回 null</returns>
|
||||
public Assembly Compile(string code, string assemblyName = null)
|
||||
{
|
||||
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
|
||||
if (assemblyName is null)
|
||||
{
|
||||
assemblyName = Path.GetRandomFileName(); // 生成随机程序集名称
|
||||
|
||||
}
|
||||
|
||||
var temp_dir = Path.Combine(Directory.GetCurrentDirectory(), "temp");
|
||||
if (!Directory.Exists(temp_dir))
|
||||
{
|
||||
Directory.CreateDirectory(temp_dir);
|
||||
}
|
||||
var savePath = Path.Combine(temp_dir, $"{assemblyName}.dll");
|
||||
|
||||
var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
|
||||
|
||||
|
||||
CSharpCompilation compilation = CSharpCompilation.Create(
|
||||
assemblyName,
|
||||
new[] { syntaxTree },
|
||||
_references,
|
||||
options
|
||||
|
||||
);
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
EmitResult result = compilation.Emit(ms);
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
Console.WriteLine("编译失败:");
|
||||
foreach (var diagnostic in result.Diagnostics)
|
||||
{
|
||||
Console.WriteLine(diagnostic.ToString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
var assembly = Assembly.Load(ms.ToArray());
|
||||
var t1 = assembly.Location;
|
||||
var t = assembly.GetType().Assembly.Location;
|
||||
|
||||
|
||||
|
||||
// 保存
|
||||
|
||||
compilation.Emit(savePath);
|
||||
return assembly;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,19 +26,33 @@ namespace Serein.NodeFlow
|
||||
/// </summary>
|
||||
public class FlowLibrary
|
||||
{
|
||||
private readonly Assembly assembly;
|
||||
private readonly Action actionOfUnloadAssmbly;
|
||||
private readonly Assembly _assembly;
|
||||
|
||||
public FlowLibrary(Assembly assembly,
|
||||
Action actionOfUnloadAssmbly)
|
||||
|
||||
|
||||
//private readonly Action actionOfUnloadAssmbly;
|
||||
/*, Action actionOfUnloadAssmbly*/
|
||||
//this.actionOfUnloadAssmbly = actionOfUnloadAssmbly;
|
||||
|
||||
public FlowLibrary(Assembly assembly)
|
||||
{
|
||||
this.assembly = assembly;
|
||||
this.actionOfUnloadAssmbly = actionOfUnloadAssmbly;
|
||||
this._assembly = assembly;
|
||||
this.FullName = Path.GetFileName(_assembly.Location);
|
||||
|
||||
this.FilePath = _assembly.Location;
|
||||
}
|
||||
|
||||
public string FullName => assembly.GetName().FullName;
|
||||
public FlowLibrary(Assembly assembly,
|
||||
string filePath)
|
||||
{
|
||||
this._assembly = assembly;
|
||||
this.FullName = Path.GetFileName(filePath); ;
|
||||
this.FilePath = filePath;
|
||||
}
|
||||
|
||||
public string Version => assembly.GetName().Version.ToString();
|
||||
public string FullName { get; private set; }
|
||||
|
||||
public string FilePath { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 加载程序集时创建的方法描述
|
||||
@@ -68,7 +82,7 @@ namespace Serein.NodeFlow
|
||||
DelegateDetailss.Clear();
|
||||
RegisterTypes.Clear();
|
||||
MethodDetailss.Clear();
|
||||
actionOfUnloadAssmbly?.Invoke();
|
||||
//actionOfUnloadAssmbly?.Invoke();
|
||||
|
||||
}
|
||||
|
||||
@@ -78,11 +92,12 @@ namespace Serein.NodeFlow
|
||||
/// <returns></returns>
|
||||
public NodeLibraryInfo ToInfo()
|
||||
{
|
||||
var assemblyName = _assembly.GetName().Name;
|
||||
return new NodeLibraryInfo
|
||||
{
|
||||
AssemblyName = assembly.GetName().Name,
|
||||
FileName = Path.GetFileName(assembly.Location),
|
||||
FilePath = assembly.Location,
|
||||
AssemblyName = assemblyName,
|
||||
FileName = this.FullName,
|
||||
FilePath = this.FilePath,
|
||||
};
|
||||
|
||||
|
||||
@@ -94,8 +109,9 @@ namespace Serein.NodeFlow
|
||||
/// </summary>
|
||||
/// <param name="assembly">程序集本身</param>
|
||||
/// <returns></returns>
|
||||
public bool LoadAssembly(Assembly assembly)
|
||||
public bool LoadAssembly()
|
||||
{
|
||||
Assembly assembly = this._assembly;
|
||||
#region 检查入参
|
||||
|
||||
// 加载DLL,创建 MethodDetails、实例作用对象、委托方法
|
||||
|
||||
@@ -39,7 +39,36 @@ namespace Serein.NodeFlow.Tool
|
||||
/// <returns></returns>
|
||||
public (NodeLibraryInfo, List<MethodDetailsInfo>) LoadLibraryOfPath(string libraryfilePath)
|
||||
{
|
||||
return LoadDllNodeInfo(libraryfilePath);
|
||||
|
||||
var dir = Path.GetDirectoryName(libraryfilePath); // 获取目录路径
|
||||
var sereinFlowBaseLibraryPath = Path.Combine(dir, SereinBaseLibrary);// 每个类库下面至少需要有“Serein.Library.dll”类库依赖
|
||||
if (!Path.Exists(sereinFlowBaseLibraryPath))
|
||||
{
|
||||
throw new Exception($"从文件加载DLL失败,目标文件夹不存在{SereinBaseLibrary}文件" );
|
||||
}
|
||||
|
||||
var flowAlc = new FlowLibraryAssemblyContext(sereinFlowBaseLibraryPath, Path.GetFileName(libraryfilePath));
|
||||
var assembly = flowAlc.LoadFromAssemblyPath(libraryfilePath); // 加载指定路径的程序集
|
||||
var reulst = LoadDllNodeInfo(assembly);
|
||||
if(reulst.Item1 is null || reulst.Item2.Count == 0)
|
||||
{
|
||||
flowAlc?.Unload(); // 卸载程序集
|
||||
flowAlc = null;
|
||||
GC.Collect(); // 强制触发GC确保卸载成功
|
||||
GC.WaitForPendingFinalizers();
|
||||
throw new Exception("从文件加载DLL失败:"+ libraryfilePath);
|
||||
}
|
||||
return reulst;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载类库
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <returns></returns>
|
||||
public (NodeLibraryInfo, List<MethodDetailsInfo>) LoadLibraryOfPath(Assembly assembly)
|
||||
{
|
||||
return LoadDllNodeInfo(assembly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -206,84 +235,44 @@ namespace Serein.NodeFlow.Tool
|
||||
/// </summary>
|
||||
public readonly static string SereinBaseLibrary = $"{nameof(Serein)}.{nameof(Serein.Library)}.dll";
|
||||
|
||||
private (NodeLibraryInfo, List<MethodDetailsInfo>) LoadDllNodeInfo(string dllFilePath)
|
||||
private (NodeLibraryInfo, List<MethodDetailsInfo>) LoadDllNodeInfo(Assembly assembly)
|
||||
{
|
||||
var fileName = Path.GetFileName(dllFilePath); // 获取文件名
|
||||
if (SereinBaseLibrary.Equals(fileName))
|
||||
|
||||
if (assembly.FullName?.ToString().Equals(typeof(IFlowEnvironment).Assembly.FullName?.ToString()) == true)
|
||||
{
|
||||
return LoadAssembly(typeof(IFlowEnvironment).Assembly, () => {
|
||||
//SereinEnv.PrintInfo(InfoType.WRAN, "基础模块不能卸载");
|
||||
});
|
||||
// 加载基础依赖
|
||||
return LoadAssembly(typeof(IFlowEnvironment).Assembly);
|
||||
}
|
||||
else
|
||||
{
|
||||
var dir = Path.GetDirectoryName(dllFilePath); // 获取目录路径
|
||||
var sereinFlowBaseLibraryPath = Path.Combine(dir, SereinBaseLibrary);
|
||||
// 每个类库下面至少需要有“Serein.Library.dll”类库依赖
|
||||
|
||||
//AssemblyLoader assemblyLoader = new AssemblyLoader(dllFilePath);
|
||||
|
||||
|
||||
var flowAlc = new FlowLibraryAssemblyContext(sereinFlowBaseLibraryPath, fileName);
|
||||
Action actionUnload = () =>
|
||||
try
|
||||
{
|
||||
flowAlc?.Unload(); // 卸载程序集
|
||||
flowAlc = null;
|
||||
GC.Collect(); // 强制触发GC确保卸载成功
|
||||
GC.WaitForPendingFinalizers();
|
||||
};
|
||||
var assembly = flowAlc.LoadFromAssemblyPath(dllFilePath); // 加载指定路径的程序集
|
||||
var assembly_result = LoadAssembly(assembly, actionUnload);
|
||||
return assembly_result;
|
||||
var assembly_result = LoadAssembly(assembly);
|
||||
return assembly_result;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return (null,[]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* var dir = Path.GetDirectoryName(dllFilePath); // 获取目录路径
|
||||
var sereinFlowLibraryPath = Path.Combine(dir, SereinLibraryDll);
|
||||
// 每个类库下面至少需要有“Serein.Library.dll”类库依赖
|
||||
var flowAlc = new FlowLibraryAssemblyContext(sereinFlowLibraryPath, fileName);
|
||||
Action actionUnload = () =>
|
||||
{
|
||||
flowAlc?.Unload(); // 卸载程序集
|
||||
flowAlc = null;
|
||||
GC.Collect(); // 强制触发GC确保卸载成功
|
||||
GC.WaitForPendingFinalizers();
|
||||
};
|
||||
var assembly = flowAlc.LoadFromAssemblyPath(dllFilePath); // 加载指定路径的程序集
|
||||
if (_myFlowLibrarys.ContainsKey(assembly.GetName().Name))
|
||||
{
|
||||
actionUnload.Invoke();
|
||||
throw new Exception($"程序集[{assembly.GetName().FullName}]已经加载过!");
|
||||
}
|
||||
FlowLibrary flowLibrary = new FlowLibrary(assembly, actionUnload);
|
||||
if (flowLibrary.LoadAssembly(assembly))
|
||||
{
|
||||
_myFlowLibrarys.TryAdd(assembly.GetName().Name, flowLibrary);
|
||||
(NodeLibraryInfo, List<MethodDetailsInfo>) result = (flowLibrary.ToInfo(),
|
||||
flowLibrary.MethodDetailss.Values.Select(md => md.ToInfo()).ToList());
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"程序集[{assembly.GetName().FullName}]加载失败");
|
||||
}*/
|
||||
}
|
||||
|
||||
private (NodeLibraryInfo, List<MethodDetailsInfo>) LoadAssembly(Assembly assembly,Action actionUnload)
|
||||
private (NodeLibraryInfo, List<MethodDetailsInfo>) LoadAssembly(Assembly assembly)
|
||||
{
|
||||
if (_myFlowLibrarys.ContainsKey(assembly.GetName().Name))
|
||||
{
|
||||
actionUnload.Invoke();
|
||||
throw new Exception($"程序集[{assembly.GetName().FullName}]已经加载过!");
|
||||
}
|
||||
|
||||
FlowLibrary flowLibrary = new FlowLibrary(assembly, actionUnload);
|
||||
var loadResult = flowLibrary.LoadAssembly(assembly); // 加载程序集
|
||||
FlowLibrary flowLibrary = new FlowLibrary(assembly);
|
||||
var loadResult = flowLibrary.LoadAssembly(); // 加载程序集
|
||||
if (loadResult)
|
||||
{
|
||||
var assemblyName = assembly.GetName().Name;
|
||||
if (string.IsNullOrEmpty(assemblyName))
|
||||
{
|
||||
actionUnload.Invoke();
|
||||
throw new Exception($"程序集[{assembly.GetName().FullName}]加载失败,没有程序集名称");
|
||||
}
|
||||
_myFlowLibrarys.TryAdd(assemblyName, flowLibrary);
|
||||
@@ -296,7 +285,6 @@ namespace Serein.NodeFlow.Tool
|
||||
}
|
||||
else
|
||||
{
|
||||
actionUnload.Invoke();
|
||||
throw new Exception($"程序集[{assembly.GetName().FullName}]加载失败");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public static class NodeMethodDetailsHelper
|
||||
/// </summary>
|
||||
public static IEnumerable<MethodInfo> GetMethodsToProcess(Type type)
|
||||
{
|
||||
return type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
return type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)
|
||||
.Where(m => m.GetCustomAttribute<NodeActionAttribute>()?.Scan == true);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user