using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Linq.Expressions; using System.Reflection; using LB_VisionProcesses; using System.Collections.Concurrent; using System.Diagnostics; namespace LB_SmartVision.ProcessRun { public class ExpressionTreeMappingEngine { private ConcurrentDictionary>> _compiledMappings; private readonly ConcurrentDictionary _processContext; public ExpressionTreeMappingEngine(ConcurrentDictionary processContext) { _processContext = processContext; _compiledMappings = new ConcurrentDictionary>>(); } public void CompileMappings(ConcurrentDictionary>> dicInputsMapping) { foreach (var processMapping in dicInputsMapping) { var processName = processMapping.Key; var actions = new List>(); foreach (var tuple in processMapping.Value) { if (string.IsNullOrEmpty(tuple.Item2?.Trim())) continue; var action = CreateMappingAction(tuple.Item1, tuple.Item2); if (action != null) actions.Add(action); } _compiledMappings[processName] = actions; } } private Action CreateMappingAction(string inputPath, string outputPath) { try { // 解析输入路径:TargetProcess.InputType.InputProperty var inputParts = inputPath.Split('.'); if (inputParts.Length < 3) return null; string targetProcessName = inputParts[0]; string inputType = inputParts[1]; // 通常是 "Inputs" string inputProperty = inputParts[2]; // 解析输出路径:SourceProcess.OutputType.OutputProperty var outputParts = outputPath.Split('.'); if (outputParts.Length < 2) return null; string sourceProcessName = outputParts[0]; string outputType = outputParts[1]; // "Inputs" 或 "Outputs" string outputProperty = outputParts.Length == 3 ? outputParts[2] : ""; // 创建表达式参数 var targetParameter = Expression.Parameter(typeof(IProcess), "targetProcess"); // 构建获取源值的表达式 var sourceValueExpression = BuildSourceValueExpression(sourceProcessName, outputType, outputProperty); if (sourceValueExpression == null) return null; // 构建设置目标值的表达式 var setTargetExpression = BuildSetTargetExpression(targetParameter, inputType, inputProperty, sourceValueExpression); if (setTargetExpression == null) return null; // 编译为委托 var lambda = Expression.Lambda>(setTargetExpression, targetParameter); return lambda.Compile(); } catch (Exception ex) { Debug.WriteLine($"创建映射动作失败: {ex.Message}"); return null; } } private Expression BuildSourceValueExpression(string sourceProcessName, string outputType, string outputProperty) { // 获取源流程实例:_processContext[sourceProcessName] var contextField = Expression.Constant(_processContext); var processNameConstant = Expression.Constant(sourceProcessName); var getItemMethod = typeof(ConcurrentDictionary).GetMethod("get_Item"); var getProcessExpr = Expression.Call(contextField, getItemMethod, processNameConstant); // 转换为 IProcess var convertExpr = Expression.Convert(getProcessExpr, typeof(IProcess)); // 添加 null 检查 var nullCheck = Expression.NotEqual(convertExpr, Expression.Constant(null, typeof(IProcess))); // 根据输出类型和属性构建获取值的表达式 Expression valueExpression = outputType switch { "Inputs" => BuildInputsValueExpression(convertExpr, outputProperty), "Outputs" => BuildOutputsValueExpression(convertExpr, outputProperty), _ => Expression.Constant(null, typeof(object)) }; // 如果源流程为 null,返回 null,否则返回值 return Expression.Condition(nullCheck, Expression.Convert(valueExpression, typeof(object)), Expression.Constant(null, typeof(object))); } private Expression BuildInputsValueExpression(Expression processExpr, string propertyName) { if (propertyName == "Image") { // 首先尝试字段,然后尝试属性 return GetMemberExpression(processExpr, "InputImage"); } else { return BuildInputsConcurrentDictionaryExpression(processExpr, propertyName); } } private Expression BuildOutputsValueExpression(Expression processExpr, string propertyName) { if (propertyName == "Image") { // 首先尝试字段,然后尝试属性 return GetMemberExpression(processExpr, "OutputImage"); } else if (propertyName == "Result") { // 首先尝试字段,然后尝试属性 return GetMemberExpression(processExpr, "Result"); } else if (propertyName == "Fixture") { // 通过 Params 获取 Fixture var paramsExpr = GetMemberExpression(processExpr, "Params"); return GetMemberExpression(paramsExpr, "Fixture"); } else { return BuildOutputsConcurrentDictionaryExpression(processExpr, propertyName); } } private Expression BuildInputsConcurrentDictionaryExpression(Expression processExpr, string propertyName) { // process.Params.Inputs[propertyName] var paramsExpr = GetMemberExpression(processExpr, "Params"); var inputsExpr = GetMemberExpression(paramsExpr, "Inputs"); var indexer = inputsExpr.Type.GetProperty("Item", new[] { typeof(string) }); if (indexer == null) throw new InvalidOperationException("Inputs 类型没有字符串索引器"); var propertyNameConstant = Expression.Constant(propertyName); return Expression.Property(inputsExpr, indexer, propertyNameConstant); } private Expression BuildOutputsConcurrentDictionaryExpression(Expression processExpr, string propertyName) { // process.Params.Outputs[propertyName] var paramsExpr = GetMemberExpression(processExpr, "Params"); var outputsExpr = GetMemberExpression(paramsExpr, "Outputs"); var indexer = outputsExpr.Type.GetProperty("Item", new[] { typeof(string) }); if (indexer == null) throw new InvalidOperationException("Outputs 类型没有字符串索引器"); var propertyNameConstant = Expression.Constant(propertyName); return Expression.Property(outputsExpr, indexer, propertyNameConstant); } /// /// 通用的成员访问方法:首先尝试字段,然后尝试属性 /// private Expression GetMemberExpression(Expression instance, string memberName) { var type = instance.Type; // 首先尝试字段 var field = type.GetField(memberName, BindingFlags.Public | BindingFlags.Instance); if (field != null) { return Expression.Field(instance, field); } // 然后尝试属性 var property = type.GetProperty(memberName, BindingFlags.Public | BindingFlags.Instance); if (property != null) { return Expression.Property(instance, property); } throw new InvalidOperationException($"在类型 {type.Name} 中找不到字段或属性: {memberName}"); } private Expression BuildSetTargetExpression(ParameterExpression targetParameter, string inputType, string inputProperty, Expression sourceValueExpression) { return inputProperty switch { "Image" => BuildSetImageExpression(targetParameter, sourceValueExpression), "Fixture" => BuildSetFixtureExpression(targetParameter, sourceValueExpression), "Result" => BuildSetResultExpression(targetParameter, inputProperty, sourceValueExpression), _ => BuildSetInputExpression(targetParameter, inputProperty, sourceValueExpression) }; } private Expression BuildSetImageExpression(ParameterExpression target, Expression sourceValue) { // target.InputImage = sourceValue var inputImageExpr = GetMemberExpression(target, "InputImage"); return Expression.Assign(inputImageExpr, Expression.Convert(sourceValue, inputImageExpr.Type)); } private Expression BuildSetFixtureExpression(ParameterExpression target, Expression sourceValue) { //// target.Params.Fixture = sourceValue ?? new Fixture() //var paramsExpr = GetMemberExpression(target, "Params"); //var fixtureExpr = GetMemberExpression(paramsExpr, "Fixture"); //// 如果源值为null,创建新的Fixture //var newFixtureExpr = Expression.New(typeof(Fixture)); //var coalesceExpr = Expression.Coalesce( // Expression.Convert(sourceValue, typeof(Fixture)), // newFixtureExpr //); //return Expression.Assign(fixtureExpr, coalesceExpr); // 如果源值为null,就设置为null,不创建新对象 var paramsExpr = GetMemberExpression(target, "Params"); var fixtureExpr = GetMemberExpression(paramsExpr, "Fixture"); var convertedSourceValue = Expression.Convert(sourceValue, typeof(Fixture)); return Expression.Assign(fixtureExpr, convertedSourceValue); } private Expression BuildSetResultExpression(ParameterExpression target, string propertyName, Expression sourceValue) { // target.Params.Inputs[propertyName] = sourceValue var paramsExpr = GetMemberExpression(target, "Params"); var inputsExpr = GetMemberExpression(paramsExpr, "Inputs"); var indexer = inputsExpr.Type.GetProperty("Item", new[] { typeof(string) }); if (indexer == null) return Expression.Empty(); var propertyNameConstant = Expression.Constant(propertyName); var targetIndexExpr = Expression.Property(inputsExpr, indexer, propertyNameConstant); return Expression.Assign(targetIndexExpr, Expression.Convert(sourceValue, targetIndexExpr.Type)); } private Expression BuildSetInputExpression(ParameterExpression target, string propertyName, Expression sourceValue) { // 检查字典是否包含该键,如果包含则赋值 var paramsExpr = GetMemberExpression(target, "Params"); var inputsExpr = GetMemberExpression(paramsExpr, "Inputs"); var containsMethod = inputsExpr.Type.GetMethod("Contains", new[] { typeof(string) }); if (containsMethod == null) return Expression.Empty(); var propertyNameConstant = Expression.Constant(propertyName); var containsCall = Expression.Call(inputsExpr, containsMethod, propertyNameConstant); // 如果包含键,则赋值 var indexer = inputsExpr.Type.GetProperty("Item", new[] { typeof(string) }); if (indexer == null) return Expression.Empty(); var targetIndexExpr = Expression.Property(inputsExpr, indexer, propertyNameConstant); var assignExpr = Expression.Assign( targetIndexExpr, Expression.Convert(sourceValue, targetIndexExpr.Type) ); // 条件表达式:if (inputs.Contains(propertyName)) { inputs[propertyName] = sourceValue; } return Expression.IfThen(containsCall, assignExpr); } public void UpdateInputs(IProcess process) { if (_compiledMappings.TryGetValue(process.strProcessName, out var actions)) { foreach (var action in actions) { try { action(process); } catch (Exception ex) { // 处理运行时异常 Debug.WriteLine($"执行映射动作失败: {ex.Message}"); } } } } public void Dispose() { foreach (var list in _compiledMappings.Values) { list.Clear(); } _compiledMappings.Clear(); } public void ClearMappings() { _compiledMappings.Clear(); } public void RemoveProcessMappings(string processName) { _compiledMappings.TryRemove(processName, out _); } } // 辅助扩展方法,用于调试 public static class ExpressionTreeDebugExtensions { public static void DebugMemberAccess(this ExpressionTreeMappingEngine engine, IProcess testProcess) { var processType = typeof(IProcess); Debug.WriteLine("=== IProcess 成员调试信息 ==="); Debug.WriteLine("字段:"); foreach (var field in processType.GetFields(BindingFlags.Public | BindingFlags.Instance)) { Debug.WriteLine($" {field.Name} : {field.FieldType.Name}"); } Debug.WriteLine("属性:"); foreach (var prop in processType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { Debug.WriteLine($" {prop.Name} : {prop.PropertyType.Name}"); } // 测试具体成员访问 try { var processExpr = Expression.Parameter(typeof(IProcess), "p"); var outputImageExpr = Expression.Field(processExpr, "OutputImage"); var lambda = Expression.Lambda>(outputImageExpr, processExpr).Compile(); var result = lambda(testProcess); Debug.WriteLine($"OutputImage 字段访问成功: {result ?? "null"}"); } catch (Exception ex) { Debug.WriteLine($"OutputImage 字段访问失败: {ex.Message}"); } } } }