/// <summary> /// 自动计算标签值 /// 采用动态代码执行方式,编译一次,采用参数传入的方式执行 /// </summary> private void ThreadAutoCalculation() { Type dynamicCode = null; //获取编译后代码,调用该类用 List <FmsTagCalculation> TagCalculations = null; //计算规则 Dictionary <string, Dictionary <string, string> > FuncAndParamTagPKNO = new Dictionary <string, Dictionary <string, string> >(); //函数和对应参数的Tag的PKNO while (!CBaseData.AppClosing) { #region 暂停 if (bPause) { System.Threading.Thread.Sleep(200); continue; } #endregion try { int index; if (bRefreshAutoCal) //刷新计算规则 { WcfClient <IFMSService> wsThis = new WcfClient <IFMSService>(); TagCalculations = wsThis.UseService(s => s.GetFmsTagCalculations("USE_FLAG = 1")); bRefreshAutoCal = false; if ((TagCalculations == null) || (!TagCalculations.Any())) { Thread.Sleep(500); continue; } string className = "C" + Guid.NewGuid().ToString("N"); #region 形成执行的代码 string execCode = "using System; \r\n" + "using System.Text; \r\n" + "using System.Collections.Generic; \r\n" + "using BFM.Common.Base; \r\n\r\n"; execCode += "public class " + className + "\r\n" + "{ \r\n"; string basicFuc = "AutoCalculation"; index = 1; FuncAndParamTagPKNO.Clear(); foreach (FmsTagCalculation calculation in TagCalculations) { FmsAssetTagSetting tagResult = GetTagSettingById(calculation.RESULT_TAG_PKNO); //结果 string exp = calculation.CALCULATION_EXPRESSION; //表达式 string funcname = basicFuc + index.ToString(); //函数名称 Dictionary <string, string> paramTas = new Dictionary <string, string>(); //参数对应的标签的PKNO, param List <string> funcParam = new List <string>(); //带类型的参数 string code = ""; string resultType = "string"; //将标签替换成参数名 foreach (var line in exp.Split(new string[] { "\r\n" }, StringSplitOptions.None)) { string ret = line; #region 替换标签值,将标签替换成参数名 string[] expTags = line.Split('{'); for (int i = 0; i < expTags.Length; i++) { string str = expTags[i]; int length = str.IndexOf('}'); if (length < 0) //没有找到 } { continue; } string tagPKNO = str.Substring(0, length); //{ } 内为PKNO string param = "{" + tagPKNO + "}"; if (paramTas.ContainsKey(tagPKNO)) //已经添加了该参数 { param = paramTas[tagPKNO]; } else { FmsAssetTagSetting tag = GetTagSettingById(tagPKNO); if (tag == null) { continue; } param = "param" + paramTas.Count; paramTas.Add(tagPKNO, param); string paramType = "string"; //所有参数传入都是string型 //string paramType = // ((calculation.CALCULATION_TYPE == 2) || // (tag.VALUE_TYPE > 0 && tag.VALUE_TYPE < 20)) // ? "double" // : "string"; funcParam.Add(paramType + " " + param); } ret = ret.Replace("{" + tagPKNO + "}", param); } #endregion if (string.IsNullOrEmpty(code)) { code = " " + ret; } else { code += Environment.NewLine + " " + ret; } } //确定返回结果类型,将code语句转换成C#的语句 if (calculation.CALCULATION_TYPE == 1) //逻辑运算 { //(结果为1,0):({标签1}==1)&&({标签2}==1)&&({标签3}==0||{标签4}==0)&&({标签5}==1) code = code.Replace("AND", "&&").Replace("and", "&&").Replace("OR", "||").Replace("or", "||"); resultType = "bool"; } else if (calculation.CALCULATION_TYPE == 2) //数值运算 { //{标签1}+3+{标签2}+4 resultType = "double"; } else if (calculation.CALCULATION_TYPE == 3) //字符运算 { //{标签1}+"123" } else if (calculation.CALCULATION_TYPE == 12) //条件数值运算 { //{标签1}==3:{标签2}+1;{标签1}==4:{标签2}+2;{标签1}==5:{标签2}+3 resultType = "double"; List <string> exps = code.Split(';').ToList(); string temp = ""; foreach (var exp1 in exps) { if (exp1.Split(':').Length < 2) { continue; } temp += " if (" + exp1.Split(':')[0] + ") { return (" + exp1.Split(':')[1] + "); } \r\n"; } temp += " return 0; \r\n"; code = temp; } else if (calculation.CALCULATION_TYPE == 13) //条件字符运算 { //{标签1}==3:{标签1}+"123";{标签1}==4:{标签1}+"123" List <string> exps = code.Split(';').ToList(); string temp = ""; foreach (var exp1 in exps) { if (exp1.Split(':').Length < 2) { continue; } temp += " if (" + exp1.Split(':')[0] + ") { return (" + exp1.Split(':')[1] + ").ToString(); } \r\n"; } temp += " return \"\"; \r\n"; code = temp; } else if (calculation.CALCULATION_TYPE == 100) //C#脚本 { //支持C#语法,最后返回值(Double/String) resultType = "string"; } else //不支持的类型 { code = $" return \"计算类型[{calculation.CALCULATION_TYPE}],不支持的类型。\"; \r\n"; } execCode += DynamicCode.BuildExecFunc(funcname, resultType, code, funcParam); //增加一个函数 index++; FuncAndParamTagPKNO.Add(funcname, paramTas); //添加 } execCode += "}\r\n"; #endregion #region 编译代码 CodeDomProvider compiler = new CSharpCodeProvider(); CompilerParameters cp = new CompilerParameters() { GenerateExecutable = false, GenerateInMemory = true, }; cp.ReferencedAssemblies.Add("BFM.Common.Base.dll"); CompilerResults cr = compiler.CompileAssemblyFromSource(cp, execCode); if (cr.Errors.HasErrors) { NetLog.Error("DeviceMonitor.ThreadAutoCalculation Invaild Code: :" + execCode); } dynamicCode = cr.CompiledAssembly.GetType(className); //获取 #endregion } if ((TagCalculations == null) || (!TagCalculations.Any()) || (dynamicCode == null) || (FuncAndParamTagPKNO.Count <= 0)) { Thread.Sleep(500); continue; } #region 获取值 index = 0; foreach (FmsTagCalculation calculation in TagCalculations) { FmsAssetTagSetting tagResult = GetTagSettingById(calculation.RESULT_TAG_PKNO); //结果 if (tagResult == null) { continue; } if (FuncAndParamTagPKNO.Count < index) { break; } string funcName = FuncAndParamTagPKNO.Keys.ToList()[index]; var tagParms = FuncAndParamTagPKNO.Values.ToList()[index]; List <object> paramValues = new List <object>(); //参数值 foreach (var tagpkno in tagParms) //参数 { object value = null; FmsAssetTagSetting tagParam = GetTagSettingById(tagpkno.Key); if (tagParam != null) { value = SafeConverter.SafeToStr(tagParam.CUR_VALUE); //if ((calculation.CALCULATION_TYPE == 2) || (tagParam.VALUE_TYPE > 0 && tagParam.VALUE_TYPE < 20)) //{ // value = SafeConverter.SafeToDouble(tagParam.CUR_VALUE); //} //else //{ // value = SafeConverter.SafeToStr(tagParam.CUR_VALUE); //} } else { value = ""; } paramValues.Add(value); } object obj = dynamicCode.InvokeMember(funcName, BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, System.Type.DefaultBinder, null, paramValues.ToArray()); string newValue = ""; //新的计算结果 #region 更新结果 if (calculation.CALCULATION_TYPE == 1) //逻辑运算 { newValue = SafeConverter.SafeToBool(obj) ? "1" : "0"; } else { newValue = SafeConverter.SafeToStr(obj); } SaveData(tagResult.PKNO, newValue); //保存更新值 #endregion index++; } #endregion } catch (Exception e) { NetLog.Error("DeviceMonitor.ThreadAutoCalculation error:", e); } Thread.Sleep(100); } }
//测试 private void BtnTest_Click(object sender, RoutedEventArgs e) { TbTestResult.Text = ""; RefreshCalculationText(); Type dynamicCode = null; //获取编译后代码,调用该类用 Dictionary <string, Dictionary <string, string> > FuncAndParamTagPKNO = new Dictionary <string, Dictionary <string, string> >(); //函数和对应参数的Tag的PKNO string className = "C" + Guid.NewGuid().ToString("N"); try { Cursor = Cursors.Wait; #region 形成执行的代码 string execCode = "using System; \r\n" + "using System.Text; \r\n" + "using System.Collections.Generic; \r\n" + "using BFM.Common.Base; \r\n\r\n"; execCode += "public class " + className + "\r\n" + "{ \r\n"; string basicFuc = "AutoCalculation"; int index = 1; FuncAndParamTagPKNO.Clear(); string exp = CalculationText; //表达式 string funcname = basicFuc + index.ToString(); //函数名称 Dictionary <string, string> paramTas = new Dictionary <string, string>(); //参数对应的标签的PKNO, param名称 List <string> funcParam = new List <string>(); //带类型的参数 string code = ""; foreach (var line in exp.Split(new string[] { "\r\n" }, StringSplitOptions.None)) { string ret = line; #region 替换标签值,将标签替换成参数名 string[] expTags = line.Split('{'); for (int i = 0; i < expTags.Length; i++) { string str = expTags[i]; int length = str.IndexOf('}'); if (length < 0) //没有找到 } { continue; } string tagPKNO = str.Substring(0, length); //{ } 内为PKNO string param = "{" + tagPKNO + "}"; if (paramTas.ContainsKey(tagPKNO)) //已经添加了该参数 { param = paramTas[tagPKNO]; } else { FmsAssetTagSetting tag = DeviceTags.FirstOrDefault(s => s.PKNO == tagPKNO); if (tag == null) { continue; } param = "param" + paramTas.Count; paramTas.Add(tagPKNO, param); string paramType = "string"; //string paramType = ((CalculationType == 2) || (tag.VALUE_TYPE > 0 && tag.VALUE_TYPE < 20)) // ? "double" // : "string"; funcParam.Add(paramType + " " + param); } ret = ret.Replace("{" + tagPKNO + "}", param); } #endregion if (string.IsNullOrEmpty(code)) { code = " " + ret; } else { code += Environment.NewLine + " " + ret; } } //C#脚本 //支持C#语法,最后返回值(Double/String) string resultType = "string"; //确定返回结果类型,将code语句转换成C#的语句 if (CalculationType == 1) //逻辑运算 { //(结果为1,0):({标签1}==1)&&({标签2}==1)&&({标签3}==0||{标签4}==0)&&({标签5}==1) code = code.Replace("AND", "&&").Replace("and", "&&").Replace("OR", "||").Replace("or", "||"); resultType = "bool"; } else if (CalculationType == 2) //数值运算 { //{标签1}+3+{标签2}+4 resultType = "double"; } else if (CalculationType == 3) //字符运算 { //{标签1}+"123" } else if (CalculationType == 12) //条件数值运算 { //{标签1}==3:{标签2}+1;{标签1}==4:{标签2}+2;{标签1}==5:{标签2}+3 resultType = "double"; List <string> exps = code.Split(';').ToList(); string temp = ""; foreach (var exp1 in exps) { if (exp1.Split(':').Length < 2) { continue; } temp += " if (" + exp1.Split(':')[0] + ") { return (" + exp1.Split(':')[1] + "); } \r\n"; } temp += " return 0; \r\n"; code = temp; } else if (CalculationType == 13) //条件字符运算 { //{标签1}==3:{标签1}+"123";{标签1}==4:{标签1}+"123" List <string> exps = code.Split(';').ToList(); string temp = ""; foreach (var exp1 in exps) { if (exp1.Split(':').Length < 2) { continue; } temp += " if (" + exp1.Split(':')[0] + ") { return (" + exp1.Split(':')[1] + ").ToString(); } \r\n"; } temp += " return \"\"; \r\n"; code = temp; } else if (CalculationType == 21) { resultType = "string";//{标签1};3 List <string> exps = code.Split(';').ToList(); string temp = ""; if (exps.Count >= 2) { int arrayIndex = SafeConverter.SafeToInt(exps[1].Trim(), 0); temp += " if ( " + exps[0].Trim() + ".Split('|').Length > " + arrayIndex + ") { return " + exps[0].Trim() + ".Split('|')[" + arrayIndex + "]; } \r\n"; } temp += " return \"\"; \r\n"; code = temp; } else if (CalculationType == 100) //C#脚本 { //支持C#语法,最后返回值(Double/String) resultType = "string"; } else //不支持的类型 { code = $" return \"计算类型[{CalculationType}],不支持的类型。\"; \r\n"; } execCode += DynamicCode.BuildExecFunc(funcname, resultType, code, funcParam); FuncAndParamTagPKNO.Add(funcname, paramTas); //添加 execCode += "}\r\n"; #endregion #region 编译代码 CodeDomProvider compiler = new CSharpCodeProvider(); CompilerParameters cp = new CompilerParameters() { GenerateExecutable = false, GenerateInMemory = true, }; cp.ReferencedAssemblies.Add("BFM.Common.Base.dll"); CompilerResults cr = compiler.CompileAssemblyFromSource(cp, execCode); if (cr.Errors.HasErrors) { WPFMessageBox.ShowError("测试失败,语法错误.\r\n" + execCode, "测试"); return; } dynamicCode = cr.CompiledAssembly.GetType(className); //获取 #endregion #region 获取值 index = 0; string funcName = FuncAndParamTagPKNO.Keys.ToList()[index]; var tagParms = FuncAndParamTagPKNO.Values.ToList()[index]; List <object> paramValues = new List <object>(); //参数值 foreach (var tagpkno in tagParms) //参数 { object value; FmsAssetTagSetting tagParam = DeviceTags.FirstOrDefault(s => s.PKNO == tagpkno.Key); if (tagParam != null) { value = SafeConverter.SafeToStr(tagParam.CUR_VALUE); //if ((CalculationType == 2) || (tagParam.VALUE_TYPE > 0 && tagParam.VALUE_TYPE < 20)) //{ // value = SafeConverter.SafeToDouble(tagParam.CUR_VALUE); //} //else //{ // value = SafeConverter.SafeToStr(tagParam.CUR_VALUE); //} } else { value = ""; } paramValues.Add(value); } object obj = dynamicCode.InvokeMember(funcName, BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, System.Type.DefaultBinder, null, paramValues.ToArray()); string newValue = ""; //新的计算结果 if (CalculationType == 1) //逻辑运算 { newValue = SafeConverter.SafeToBool(obj) ? "1" : "0"; } else { newValue = SafeConverter.SafeToStr(obj); } Console.WriteLine("测试结果:" + newValue); TbTestResult.Text = newValue; #endregion WPFMessageBox.ShowInfo("测试成功. \r\n测试结果为:" + newValue, "测试"); } catch (Exception ex) { Console.WriteLine(ex); WPFMessageBox.ShowError("测试失败,错误为:" + ex.Message, "测试"); } finally { Cursor = Cursors.Arrow; } }