using LB_VisionProcesses;
|
using System;
|
using System.Diagnostics;
|
using System.Linq;
|
using System.Reflection;
|
using System.Reflection.Emit;
|
using System.Text.Json.Nodes;
|
using System.Threading;
|
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TreeView;
|
|
namespace LB_VisionFlowNode
|
{
|
/// <summary>
|
/// 插件节点方法信息
|
/// </summary>
|
public class PluginNodeMethodInfo
|
{
|
public string DisplayName { get; set; }
|
public string FullTypeName { get; set; }
|
public string Category { get; set; }
|
public string Group { get; set; }
|
public string Description { get; set; }
|
}
|
public class IFlowContext
|
{
|
public readonly Dictionary<string, MethodInfo> _nodeMethods
|
= new Dictionary<string, MethodInfo>();
|
|
public readonly Dictionary<string, List<MethodInfo>> _groupedMethods
|
= new Dictionary<string, List<MethodInfo>>();
|
|
public readonly Dictionary<string, Func<FlowNode, bool>> _nodeDelegates
|
= new Dictionary<string, Func<FlowNode, bool>>();
|
|
public void InitializeMethods()
|
{
|
var methods = GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance);
|
|
foreach (var method in methods)
|
{
|
var nodeAttr = method.GetCustomAttribute<NodeAttribute>();
|
if (nodeAttr != null)
|
{
|
// 使用描述作为键值
|
_nodeMethods[nodeAttr.Description] = method;
|
|
// 按组分类
|
if (!_groupedMethods.ContainsKey(nodeAttr.Group))
|
{
|
_groupedMethods[nodeAttr.Group] = new List<MethodInfo>();
|
}
|
_groupedMethods[nodeAttr.Group].Add(method);
|
}
|
}
|
}
|
|
public void InitializeDelegates()
|
{
|
foreach (var kvp in _nodeMethods)
|
{
|
var method = kvp.Value;
|
var parameters = method.GetParameters();
|
|
if (parameters.Length == 0)
|
{
|
// 无参数方法
|
var action = (Action)Delegate.CreateDelegate(typeof(Action), this, method);
|
_nodeDelegates[kvp.Key] = (node) => { action(); return node.Result; };
|
}
|
else if (parameters.Length == 1 && parameters[0].ParameterType == typeof(FlowNode))
|
{
|
// 带FlowNode参数的方法
|
var action = (Action<FlowNode>)Delegate.CreateDelegate(typeof(Action<FlowNode>), this, method);
|
_nodeDelegates[kvp.Key] = (node) => { action(node); return node.Result; };
|
}
|
}
|
}
|
|
public virtual bool ExecuteNode(FlowNode node)
|
{
|
if (string.IsNullOrEmpty(node.Description))
|
return false;
|
|
// 使用委托缓存,避免反射开销
|
if (_nodeDelegates.TryGetValue(node.Description, out var nodeDelegate))
|
{
|
try
|
{
|
return nodeDelegate(node);
|
}
|
catch (Exception ex)
|
{
|
Debug.WriteLine($"执行节点失败: {ex.Message}");
|
return false;
|
}
|
}
|
|
return false;
|
}
|
|
public Dictionary<string, MethodInfo> GetAvailableNodes()
|
{
|
return _nodeMethods.ToDictionary(
|
kvp => kvp.Key,
|
kvp => kvp.Value
|
);
|
}
|
|
// 获取按组分组的可用节点
|
public Dictionary<string, List<ToolStripMenuItem>> GetGroupedMenuItems(EventHandler clickHandler)
|
{
|
var groupedMenuItems = new Dictionary<string, List<ToolStripMenuItem>>();
|
|
foreach (var group in _groupedMethods)
|
{
|
var menuItems = new List<ToolStripMenuItem>();
|
|
foreach (var method in group.Value)
|
{
|
var nodeAttr = method.GetCustomAttribute<NodeAttribute>();
|
var menuItem = new ToolStripMenuItem
|
{
|
Text = nodeAttr.Name,
|
Tag = nodeAttr.Description, // 存储描述作为标识
|
ToolTipText = nodeAttr.Description
|
};
|
|
if (clickHandler != null)
|
{
|
menuItem.Click += clickHandler;
|
}
|
|
menuItems.Add(menuItem);
|
}
|
|
groupedMenuItems[group.Key] = menuItems;
|
}
|
|
return groupedMenuItems;
|
}
|
|
|
// 获取按类别分组的菜单项
|
public Dictionary<string, List<ToolStripMenuItem>> GetCategorizedMenuItems(EventHandler clickHandler)
|
{
|
var categorizedMethods = new Dictionary<string, List<MethodInfo>>();
|
|
foreach (var method in _nodeMethods.Values)
|
{
|
var nodeAttr = method.GetCustomAttribute<NodeAttribute>();
|
if (!categorizedMethods.ContainsKey(nodeAttr.Category))
|
{
|
categorizedMethods[nodeAttr.Category] = new List<MethodInfo>();
|
}
|
categorizedMethods[nodeAttr.Category].Add(method);
|
}
|
|
var categorizedMenuItems = new Dictionary<string, List<ToolStripMenuItem>>();
|
|
foreach (var category in categorizedMethods)
|
{
|
var menuItems = new List<ToolStripMenuItem>();
|
|
foreach (var method in category.Value)
|
{
|
var nodeAttr = method.GetCustomAttribute<NodeAttribute>();
|
var menuItem = new ToolStripMenuItem
|
{
|
Text = nodeAttr.Name,
|
Tag = nodeAttr.Description,
|
ToolTipText = $"{nodeAttr.Group} - {nodeAttr.Description}"
|
};
|
|
if (clickHandler != null)
|
{
|
menuItem.Click += clickHandler;
|
}
|
|
menuItems.Add(menuItem);
|
}
|
|
categorizedMenuItems[category.Key] = menuItems;
|
}
|
|
return categorizedMenuItems;
|
}
|
|
[Node("开始", "控制", "Logic", "开始")]
|
public virtual void 开始(FlowNode node) { node.Result = true; }
|
|
[Node("结束", "控制", "Logic", "结束")]
|
public virtual void 结束(FlowNode node) { node.Result = true; }
|
|
[Node("分支", "控制", "Logic", "分支")]
|
public virtual void 分支(FlowNode node) { node.Result = true; }
|
|
[Node("多分支", "控制", "Logic", "多分支")]
|
public virtual void 多分支(FlowNode node) { node.Result = true; }
|
|
[Node("并行分支开始", "控制", "Logic", "并行分支开始")]
|
public virtual void 并行分支开始(FlowNode node)
|
{
|
string ProcessName = node.Text;
|
node.BranchIndex = "-1";
|
try
|
{
|
for (int i = 0; i < node.BranchNodes.Count; i++)
|
{
|
if (i == 0)
|
node.BranchIndex = "0;";
|
else
|
node.BranchIndex += $"{i.ToString()};";
|
}
|
node.Result = true;
|
}
|
catch { node.Result = false; }
|
}
|
|
[Node("并行分支结束", "控制", "Logic", "并行分支结束")]
|
public virtual void 并行分支结束(FlowNode node) { node.Result = true; }
|
}
|
public class FlowContext : IFlowContext
|
{
|
/// <summary>
|
/// 运行标记
|
/// </summary>
|
public bool bRuning = false;
|
|
/// <summary>
|
/// 运行完成
|
/// </summary>
|
public bool bCompleted = true;
|
|
/// <summary>
|
/// 运行结果
|
/// </summary>
|
public bool Result = false;
|
|
/// <summary>
|
/// 运行消息
|
/// </summary>
|
public string Msg = string.Empty;
|
|
/// <summary>
|
/// 运行时间
|
/// </summary>
|
public double RunTime = 0;
|
|
/// <summary>
|
/// 开始时间
|
/// </summary>
|
public DateTime StartTime = DateTime.Now;
|
|
public FlowContext()
|
{
|
//GenerateFixedNodeMethods();
|
InitializeMethods();
|
InitializeDelegates();
|
}
|
|
|
// 统一的动态节点执行辅助方法(可选)
|
private void RunNodeAsync(FlowNode node)
|
{
|
// 调用基类的ExecuteNode
|
node.Result = ExecuteNode(node);
|
if (node.Result)
|
{
|
Debug.WriteLine($"{node.Text} 运行完成");
|
}
|
else
|
{
|
Msg += $"[{node.Text}] 运行失败";
|
Result = false;
|
}
|
}
|
|
#region 注册工具事件
|
|
[Node("相机取图", "取像工具", "Basic", "相机取图")]
|
public void 相机取图(FlowNode node) { RunNodeAsync(node); }
|
|
[Node("Halcon2D斑点工具", "Halcon2D工具", "Basic", "Halcon2D斑点工具")]
|
public void Halcon2D斑点工具(FlowNode node) { RunNodeAsync(node); }
|
|
[Node("通讯模块", "通讯模块工具", "Basic", "通讯模块")]
|
public void 通讯模块(FlowNode node) { RunNodeAsync(node); }
|
// [Process("Halcon图像增强", Category = "Halcon2D工具", Description = "创建图像增强工具")]
|
|
[Node("Halcon2D图像增强", "Halcon2D工具", "Basic", "Halcon2D图像增强")]
|
public void Halcon2D图像增强(FlowNode node) { RunNodeAsync(node); }
|
|
[Node("Halcon2D图像滤波", "Halcon2D工具", "Basic", "Halcon2D图像滤波")]
|
public void Halcon2D图像滤波(FlowNode node) { RunNodeAsync(node); }
|
|
#endregion
|
|
// 重写原有Node方法,添加业务逻辑
|
[Node("开始", "控制", "Logic", "开始")]
|
public override void 开始(FlowNode node)
|
{
|
StartTime = DateTime.Now;
|
RunTime = 0;
|
|
Result = true;
|
bRuning = true;
|
bCompleted = false;
|
Msg = string.Empty;
|
node.Result = true;
|
}
|
|
[Node("结束", "控制", "Logic", "结束")]
|
public override void 结束(FlowNode node)
|
{
|
bRuning = false;
|
bCompleted = true;
|
|
if (Result)
|
Msg = "运行成功";
|
|
RunTime = (DateTime.Now - StartTime).TotalMilliseconds;
|
node.Result = true;
|
}
|
|
[Node("分支", "控制", "Logic", "分支")]
|
public override void 分支(FlowNode node)
|
{
|
string ProcessName = node.Text;
|
node.BranchIndex = "-1";
|
node.Result = true;
|
try
|
{
|
if (node.Break)
|
{
|
node.BranchIndex = "0";
|
node.Result = true;
|
return;
|
}
|
|
node.BranchIndex = 0.ToString();
|
Debug.WriteLine($"{ProcessName},分支{node.BranchIndex}运行完成");
|
}
|
catch (Exception ex)
|
{
|
node.Result = false;
|
Result &= false;
|
Msg = $"[{ProcessName}]运行发生意外,{ex.Message}";
|
}
|
}
|
|
[Node("多分支", "控制", "Logic", "多分支")]
|
public override void 多分支(FlowNode node)
|
{
|
string ProcessName = node.Text;
|
node.BranchIndex = "-1";
|
node.Result = true;
|
try
|
{
|
if (node.Break)
|
{
|
node.BranchIndex = "0";
|
node.Result = true;
|
return;
|
}
|
|
node.BranchIndex = 0.ToString();
|
Debug.WriteLine($"{ProcessName},分支{node.BranchIndex}运行完成");
|
}
|
catch (Exception ex)
|
{
|
node.Result = false;
|
Result &= false;
|
Msg = $"[{ProcessName}]运行发生意外,{ex.Message}";
|
}
|
}
|
|
}
|
|
}
|