添加项目文件。

This commit is contained in:
czj
2026-06-05 10:57:09 +08:00
parent f29671b374
commit d960cb5912
166 changed files with 15996 additions and 0 deletions

View File

@@ -0,0 +1,590 @@
using UIShare.UIViewModel;
using UIShare.GlobalVariable;
using Common.Attributes;
using Logger;
using Microsoft.IdentityModel.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Xml;
using Model;
using static UIShare.UIViewModel.ParameterModel;
using UIShare.ViewModelBase;
using NLog;
namespace TestingModule.ViewModels
{
public class CommandTreeViewModel:NavigateViewModelBase
{
#region
private string _SearchText;
public string SearchText
{
get => _SearchText;
set => SetProperty(ref _SearchText, value);
}
private ObservableCollection<InstructionNode> _instructionTree = new();
public ObservableCollection<InstructionNode> InstructionTree
{
get => _instructionTree;
set => SetProperty(ref _instructionTree, value);
}
public ProgramModel Program
{
get => _ScopedContext.Program;
set
{
if (_ScopedContext.Program != value)
{
_ScopedContext.Program = value;
RaisePropertyChanged();
}
}
}
public ObservableCollection<Assembly> Assemblies
{
get => _ScopedContext.Assemblies;
set
{
if (_ScopedContext.Assemblies != value)
{
_ScopedContext.Assemblies = value;
RaisePropertyChanged();
}
}
}
private ObservableCollection<SubProgramItem> _subPrograms = new();
public ObservableCollection<SubProgramItem> SubPrograms
{
get => _subPrograms;
set => SetProperty(ref _subPrograms, value);
}
private Dictionary<object, InstructionNode> _treeNodeMap = new();
public Dictionary<object, InstructionNode> TreeNodeMap
{
get => _treeNodeMap;
set => SetProperty(ref _treeNodeMap, value);
}
private Dictionary<string, XmlDocument> _xmlDocumentCache = new();
public Dictionary<string, XmlDocument> XmlDocumentCache
{
get => _xmlDocumentCache;
set => SetProperty(ref _xmlDocumentCache, value);
}
#endregion
public ICommand LoadedCommand { get; set; }
public ICommand SearchEnterCommand { get; set; }
public ICommand TreeDoubleClickCommand { get; set; }
public ICommand ReloadCommand { get; set; }
private ScopedContext _ScopedContext { get; set; }
private readonly SystemConfig _systemConfig;
private readonly GlobalInfo _globalInfo;
public CommandTreeViewModel(IContainerProvider containerProvider, ScopedContext scopedContext, SystemConfig systemConfig, GlobalInfo globalInfo) : base(containerProvider)
{
_ScopedContext = scopedContext;
_systemConfig = systemConfig;
_globalInfo = globalInfo;
LoadedCommand = new DelegateCommand(Loaded);
SearchEnterCommand = new DelegateCommand(Search);
TreeDoubleClickCommand = new DelegateCommand<object>(TreeDoubleClick);
ReloadCommand = new DelegateCommand(Reload);
}
#region
private void Reload()
{
LoadAllAssemblies();
LoadSubPrograms();
LoadInstructionsToTreeView();
}
private void TreeDoubleClick(object obj)
{
if (!_globalInfo.IsAdmin) return;
if(obj is InstructionNode Node)
{
if(Node.Children.Count == 0)
{
int index = _ScopedContext.SelectedStep?.Index >= 0 ? _ScopedContext.SelectedStep.Index : -1;
if (Node.Tag is MethodInfo method)
{
AddMethodToProgram(method, index);
}
else if(Node.Tag is string tag)
{
switch (tag)
{
case "循环开始":
AddLoopStartStep(index);
break;
case "循环结束":
AddLoopEndStep(index);
break;
}
}
else if(Node.Tag is SubProgramItem subProgram)
{
AddSubProgramToProgram(subProgram, index);
}
}
}
}
private void Search()
{
}
private void Loaded()
{
LoadAllAssemblies();
LoadSubPrograms();
LoadInstructionsToTreeView();
}
#endregion
#region
/// <summary>
/// 加载指定目录下的所有DLL
/// </summary>
private void LoadAllAssemblies()
{
Assemblies.Clear();
foreach (var dllPath in Directory.GetFiles(_systemConfig.DLLFilePath, "*.dll"))
{
try
{
var assembly = Assembly.LoadFile(dllPath);
Assemblies.Add(assembly);
// 加载对应的XML注释文件 (项目没有用到)
//string xmlPath = Path.ChangeExtension(dllPath, ".xml");
//if (File.Exists(xmlPath))
//{
// try
// {
// XmlDocument xmlDoc = new XmlDocument();
// xmlDoc.Load(xmlPath);
// _xmlDocumentCache[assembly.FullName!] = xmlDoc;
// }
// catch (Exception xmlEx)
// {
// LoggerHelper.WarnWithNotify($"加载XML注释失败: {Path.GetFileName(xmlPath)} - {xmlEx.Message}");
// }
//}
}
catch (Exception ex)
{
LoggerHelper.WarnWithNotify($"无法加载程序集 {Path.GetFileName(dllPath)}: {ex.Message}");
}
}
}
// 子程序加载方法
private void LoadSubPrograms()
{
SubPrograms.Clear();
if (!Directory.Exists(_systemConfig.SubProgramFilePath))
{
Directory.CreateDirectory(_systemConfig.SubProgramFilePath);
return;
}
foreach (var filePath in Directory.GetFiles(_systemConfig.SubProgramFilePath, "*.adp"))
{
try
{
SubPrograms.Add(new SubProgramItem
{
Name = Path.GetFileNameWithoutExtension(filePath),
FilePath = filePath
});
}
catch (Exception ex)
{
LoggerHelper.WarnWithNotify($"加载子程序错误: {filePath} - {ex.Message}");
}
}
}
/// <summary>
/// 加载指令集到TreeView
/// </summary>
private void LoadInstructionsToTreeView()
{
InstructionTree.Clear();
var controlRootNode = new InstructionNode
{
Name = "系统指令",
Tag = "ControlRoot"
};
InstructionTree.Add(controlRootNode);
// 循环开始
controlRootNode.Children.Add(new InstructionNode
{
Name = "循环开始",
Tag = "循环开始"
});
// 循环结束
controlRootNode.Children.Add(new InstructionNode
{
Name = "循环结束",
Tag = "循环结束"
});
// ----------------------
// 子程序 根节点
// ----------------------
var subProgramRoot = new InstructionNode
{
Name = "子程序",
Tag = "SubProgramRoot"
};
InstructionTree.Add(subProgramRoot);
foreach (var subProgram in SubPrograms)
{
subProgramRoot.Children.Add(new InstructionNode
{
Name = subProgram.Name,
Tag = subProgram,
});
}
// ----------------------
// 动态 DLL 指令
// ----------------------
foreach (var assembly in Assemblies)
{
List<Type> validTypes = new List<Type>();
try
{
var types = assembly.GetTypes().Where(t =>
t.IsPublic &&
!t.IsNested &&
(t.IsClass || t.IsValueType) &&
(!t.IsAbstract || t.IsSealed) &&
t.GetCustomAttribute<ADPCommandAttribute>() != null);
foreach (var type in types)
{
if (type.GetCustomAttribute<BrowsableAttribute>()?.Browsable == false)
continue;
var allMethods = new HashSet<MethodInfo>();
GetPublicMethods(type, allMethods);
if (allMethods.Count > 0)
validTypes.Add(type);
}
}
catch (Exception ex)
{
LoggerHelper.ErrorWithNotify($"加载类型错误: {assembly.FullName} - {ex.Message}");
}
if (validTypes.Count > 0)
{
var assemblyNode = new InstructionNode
{
Name = assembly.GetName().Name,
Tag = assembly
};
InstructionTree.Add(assemblyNode);
TreeNodeMap[assembly] = assemblyNode;
foreach (var type in validTypes)
{
//拦截没有在设备列表中的设备类型
//if (SystemConfig.Instance.DeviceList.Where(x=>x.Remark==type.Name).ToList().Count==0 && type.FullName.Contains("DeviceCommand.Device"))
//{
// continue;
//}
var typeNode = new InstructionNode
{
Name = type.Name,
Tag = type,
};
assemblyNode.Children.Add(typeNode);
TreeNodeMap[type] = typeNode;
var allMethods = new HashSet<MethodInfo>();
GetPublicMethods(type, allMethods);
foreach (var method in allMethods)
{
if (method.IsSpecialName) continue;
if (method.DeclaringType == typeof(object)) continue;
string[] ignoreMethods = { "GetType", "ToString", "Equals", "GetHashCode" };
if (ignoreMethods.Contains(method.Name)) continue;
if (method.GetCustomAttribute<BrowsableAttribute>()?.Browsable == false)
continue;
if (type.IsAbstract && type.IsSealed && !method.IsStatic) continue;
var parameters = method.GetParameters();
var paramText = string.Join(", ", parameters.Select(p => $"{p.ParameterType.Name} {p.Name}"));
var methodNode = new InstructionNode
{
Name = $"{method.Name}({paramText})",
Tag = method,
};
typeNode.Children.Add(methodNode);
TreeNodeMap[method] = methodNode;
}
}
}
}
}
#endregion
#region
/// <summary>
/// 递归获取类型的所有公共方法(包括继承的方法),但跳过被重写的方法
/// </summary>
/// <param name="type">要处理的目标类型</param>
/// <param name="methods">存储方法的集合</param>
private void GetPublicMethods(Type type, HashSet<MethodInfo> methods)
{
// 获取当前类型的所有公共方法(包括继承的)
var allMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)
.Where(m => !m.IsSpecialName &&
m.DeclaringType != typeof(object))
.ToList();
// 按方法签名分组
var groupedMethods = allMethods
.GroupBy(m => new { m.Name, Parameters = string.Join(",", m.GetParameters().Select(p => p.ParameterType.FullName)) });
foreach (var group in groupedMethods)
{
// 从组中选择声明类型最接近当前类型(即继承层次最深)的方法
MethodInfo? selectedMethod = null;
int minDepth = int.MaxValue;
foreach (var method in group)
{
// 计算声明类型的深度
int depth = 0;
Type? current = type;
Type declaringType = method.DeclaringType!;
while (current != null && current != declaringType)
{
depth++;
current = current.BaseType;
}
// 如果找到声明类型且在继承链上
if (current == declaringType)
{
if (selectedMethod == null || depth < minDepth)
{
selectedMethod = method;
minDepth = depth;
}
}
}
if (selectedMethod != null)
{
methods.Add(selectedMethod);
}
}
}
#endregion
#region
private void AddMethodToProgram(MethodInfo method, int insertIndex = -1)
{
try
{
var newStep = new StepModel
{
Name = method.Name,
StepType = "方法",
Method = new MethodModel
{
FullName = method.DeclaringType?.FullName,
Name = method.Name
}
};
// 添加输入参数
foreach (var param in method.GetParameters())
{
newStep.Method.Parameters.Add(new ParameterModel
{
Name = param.Name!,
Type = param.ParameterType,
Category = ParameterCategory.Input
});
}
// 添加输出参数(返回值)
Type returnType = method.ReturnType;
if (returnType == typeof(Task))
{
// 不添加输出参数(无返回值)
}
else if (returnType.IsGenericType &&
returnType.GetGenericTypeDefinition() == typeof(Task<>))
{
// 提取实际返回类型(如 Task<bool> -> bool
Type actualType = returnType.GetGenericArguments()[0];
newStep.Method.Parameters.Add(new ParameterModel
{
Name = "Result",
Type = actualType, // 使用实际类型
Category = ParameterCategory.Output
});
}
else if (returnType != typeof(void))
{
// 同步方法正常添加
newStep.Method.Parameters.Add(new ParameterModel
{
Name = "Result",
Type = returnType,
Category = ParameterCategory.Output
});
}
// 添加到程序
if(_ScopedContext.SelectedStepList == "主程序")
{
if(insertIndex >= 0 && insertIndex <= Program.StepCollection.Count) Program.StepCollection.Insert(insertIndex, newStep);
else Program.StepCollection.Add(newStep); }
else
{
if (insertIndex >= 0 && insertIndex <= Program.ErrorStepCollection.Count) Program.ErrorStepCollection.Insert(insertIndex, newStep);
else Program.ErrorStepCollection.Add(newStep);
}
}
catch (Exception ex)
{
LoggerHelper.ErrorWithNotify($"添加方法失败: {method.Name} - {ex.Message}");
}
}
private void AddSubProgramToProgram(SubProgramItem subProgram, int insertIndex = -1)
{
try
{
var newStep = new StepModel
{
Name = subProgram.Name,
StepType = "子程序"
};
var jsonstr = File.ReadAllText($"{subProgram.FilePath}");
var tmp = JsonConvert.DeserializeObject<ProgramModel>(jsonstr);
if (tmp != null)
{
newStep.SubProgram = tmp;
}
// 添加到程序
if (_ScopedContext.SelectedStepList == "主程序")
{
if (insertIndex >= 0 && insertIndex <= Program.StepCollection.Count) Program.StepCollection.Insert(insertIndex, newStep);
else Program.StepCollection.Add(newStep);
}
else
{
if (insertIndex >= 0 && insertIndex <= Program.ErrorStepCollection.Count) Program.ErrorStepCollection.Insert(insertIndex, newStep);
else Program.ErrorStepCollection.Add(newStep);
}
}
catch (Exception ex)
{
LoggerHelper.ErrorWithNotify($"添加子程序失败: {subProgram.Name} - {ex.Message}");
}
}
private void AddLoopStartStep(int insertIndex = -1)
{
var newStep = new StepModel
{
Name = "循环开始",
StepType = "循环开始",
LoopCount = 1,
Method = new() { Parameters = [new() { Name = "循环次数", Type = typeof(int), Category = ParameterCategory.Input }] }
};
// 添加到程序
if (_ScopedContext.SelectedStepList == "主程序")
{
if (insertIndex >= 0) Program.StepCollection.Insert(insertIndex, newStep);
else Program.StepCollection.Add(newStep);
}
else
{
if (insertIndex >= 0) Program.ErrorStepCollection.Insert(insertIndex, newStep);
else Program.ErrorStepCollection.Add(newStep);
}
}
private void AddLoopEndStep(int insertIndex = -1)
{
// 查找最近的未匹配循环开始
StepModel? lastUnmatchedLoopStart = null;
for (int i = Program.StepCollection.Count - 1; i >= 0; i--)
{
if (Program.StepCollection[i].StepType == "循环开始")
{
bool isMatched = Program.StepCollection.Any(s => s.StepType == "循环结束" && s.LoopStartStepId == Program.StepCollection[i].ID);
if (!isMatched)
{
lastUnmatchedLoopStart = Program.StepCollection[i];
break;
}
}
}
var newStep = new StepModel
{
Name = "循环结束",
StepType = "循环结束",
LoopStartStepId = lastUnmatchedLoopStart?.ID
};
// 添加到程序
if (_ScopedContext.SelectedStepList == "主程序")
{
if (insertIndex >= 0) Program.StepCollection.Insert(insertIndex, newStep);
else Program.StepCollection.Add(newStep);
}
else
{
if (insertIndex >= 0) Program.ErrorStepCollection.Insert(insertIndex, newStep);
else Program.ErrorStepCollection.Add(newStep);
}
}
#endregion
}
}