Ejemplo n.º 1
0
        /// <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);
            }
        }
Ejemplo n.º 2
0
        //测试
        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;
            }
        }