This action will force synchronization from 盘古软件/SharpSCADA, which will overwrite any changes that you have made since you forked the repository, and can not be recovered!!!
Synchronous operation will process in the background and will refresh the page when finishing processing. Please be patient.
using System;using System.Collections.Generic;using System.Linq.Expressions;using System.Reflection;using System.Runtime.InteropServices;namespace DataService{public class ExpressionEval : IDisposable{Expression _param1;List<ITag> _tagList = new List<ITag>();public List<ITag> TagList{get{return _tagList;}}IDataServer _server;public ExpressionEval(IDataServer server){_server = server;_param1 = Expression.Constant(this);}public Delegate Eval(string expression){if (string.IsNullOrEmpty(expression)) return null;var lambda = ComplieRpnExp(RpnExpression(expression));if (lambda != null) return lambda.Compile();return null;}public Delegate WriteEval(string expression){if (_server == null || string.IsNullOrEmpty(expression)) return null;if (_server[expression.ToUpper()] != null){return new Func<object, int>((object value) => { return WriteTag(expression, value); });}return null;}public Func<int> WriteEval(string expression1, string expression2){if (_server == null || string.IsNullOrEmpty(expression2)) return null;if (_server[expression1.ToUpper()] != null){var dele = Eval(expression2);var funcbool = dele as Func<bool>;if (funcbool != null)return () => { return WriteTag(expression1, funcbool()); };var funcint = dele as Func<int>;if (funcint != null)return () => { return WriteTag(expression1, funcint()); };var funcfloat = dele as Func<float>;if (funcfloat != null)return () => { return WriteTag(expression1, funcfloat()); };var funcstring = dele as Func<string>;if (funcstring != null)return () => { return WriteTag(expression1, funcstring()); };}return null;}public static bool ValidationExpression(string expression){return true;//可加入正则表达式验证}/// <summary>/// 操作符运算级别/// </summary>/// <param name="strOperator">操作符</param>/// <returns>操作运算符,空格返回0,出错返回-1</returns>private static byte GetOperatorLevel(char strOperator){switch (strOperator){case '~':return 10;case '*':case '/':case '%':return 9;case '+':case '-':return 8;case '>':case '<':return 7;case '&':return 6;case '^':return 5;case '|':return 4;case '=':case '!':case '?':return 3;case '(':return 2;case ')':return 1;//case ':':default:return 0;}}/// <summary>/// 将中缀表达式转换为逆波兰表达式/// </summary>/// <param name="expression">标准中缀表达式</param>/// <returns>标准逆波兰表达式</returns>public static List<string> RpnExpression(string expression){//加入结束标记//定义出栈和入栈堆栈string[] strNum = expression.Split('~', '%', '>', '<', '=', '!', '&', '|', '?', '#', '^', '+', '-', '*', '/', '(', ')');if (strNum.Length < 2) return new List<string>() { expression };//操作运算符堆栈Stack<Operator> oper = new Stack<Operator>();//定义输出堆栈List<string> output = new List<string>();//定义前缀表达式字符读取指针int i = 0;//定义当前读取数字数组指针int n = -1;//定义操作运算符级别函数Operator op = new Operator();//输出堆栈的大小int intStackCount = 0;//从左到右读取前缀表达式while (i < expression.Length){//读取一个字符char strChar = expression[i];//取字符的运算级别if (strChar == '#') { i++; continue; }byte intLevel = GetOperatorLevel(strChar);if (intLevel == 0)//数字直接推入输出堆栈{while (n++ < strNum.Length){if (strNum[n] != ""){output.Add(strNum[n]);i += strNum[n].Length;//移动数组指针break;}}}else //操作字符根据运算字符级别推入运算符堆栈{if (oper.Count == 0){//运算符堆栈为空,直接推入堆栈oper.Push(new Operator(strChar, intLevel));//移动字符读取指针i++;}else{op = oper.Peek();if (intLevel > op.Level || intLevel == 2){//运算字符比运算符堆栈最后的级别高或者运算符为'('直接推入运算符堆栈oper.Push(new Operator(strChar, intLevel));//移动字符读取指针i++;}else{//运算字符不高于运算符堆栈最后的级别,则将运算符堆栈出栈,直到比其高为止intStackCount = oper.Count;for (int m = 0; m < intStackCount; m++){op = oper.Peek();if (op.Level >= intLevel){//将操作符出栈并压入输入堆栈char o = op.OperatorStack;if (!(o == ')' || o == '(')){output.Add(o.ToString());}oper.Pop();if (op.Level == 2){//如果操作符堆栈中最后的操作符为'('则停止出栈i++;break;}}else{//直到运算符已经高出运算符栈中最后的级别,则入栈oper.Push(new Operator(strChar, intLevel));i++;break;}}}}}}intStackCount = oper.Count;for (int m = 0; m < intStackCount; m++){op = oper.Peek();output.Add(op.OperatorStack.ToString());oper.Pop();}return output;}/// <summary>/// 解逆波兰表达式/// </summary>/// <param name="expression">标准逆波兰表达式</param>/// <returns>逆波兰表达式的解</returns>public LambdaExpression ComplieRpnExp(List<string> strNum){_tagList.Clear();//拆分逆波兰表达式int intLenth = strNum.Count;if (intLenth == 0) return null;//定义数字堆栈try{Stack<Expression> number = new Stack<Expression>();for (int i = 0; i < intLenth; i++){string expr = strNum[i];switch (expr){case "~":if (number.Count > 0){Expression left = number.Pop();number.Push(Expression.Not(left));}break;case "*":if (number.Count > 1){Expression right = number.Pop();Expression left = number.Pop();if (left.Type != right.Type){if (left.Type != typeof(float))left = Expression.Convert(left, typeof(float));if (right.Type != typeof(float))right = Expression.Convert(right, typeof(float));}number.Push(Expression.Multiply(left, right));}break;case "/":if (number.Count > 1){Expression right = number.Pop();Expression left = number.Pop();if (left.Type != right.Type){if (left.Type != typeof(float))left = Expression.Convert(left, typeof(float));if (right.Type != typeof(float))right = Expression.Convert(right, typeof(float));}number.Push(Expression.Divide(left, right));}break;case "%":if (number.Count > 1){Expression right = number.Pop();Expression left = number.Pop();if (left.Type != right.Type){if (left.Type != typeof(int))left = Expression.Convert(left, typeof(int));if (right.Type != typeof(int))right = Expression.Convert(right, typeof(int));}number.Push(Expression.Modulo(left, right));}break;case "+":if (number.Count > 1){Expression right = number.Pop();Expression left = number.Pop();if (left.Type == typeof(string) || right.Type == typeof(string)){if (left.Type != typeof(string))left = Expression.Convert(left, typeof(object));if (right.Type != typeof(string))right = Expression.Convert(right, typeof(object));number.Push(Expression.Call(typeof(string).GetMethod("Concat", new Type[] { typeof(object), typeof(object) }), left, right));}else{if (left.Type != right.Type){if (left.Type != typeof(float))left = Expression.Convert(left, typeof(float));if (right.Type != typeof(float))right = Expression.Convert(right, typeof(float));}number.Push(Expression.Add(left, right));}}break;case "-":if (number.Count > 1){Expression right = number.Pop();Expression left = number.Pop();if (left.Type != right.Type){if (left.Type != typeof(float))left = Expression.Convert(left, typeof(float));if (right.Type != typeof(float))right = Expression.Convert(right, typeof(float));}number.Push(Expression.Subtract(left, right));}break;case ">":if (number.Count > 1){Expression right = number.Pop();Expression left = number.Pop();if (left.Type != right.Type){if (left.Type != typeof(float))left = Expression.Convert(left, typeof(float));if (right.Type != typeof(float))right = Expression.Convert(right, typeof(float));}number.Push(Expression.GreaterThan(left, right));}break;case "<":if (number.Count > 1){Expression right = number.Pop();Expression left = number.Pop();if (left.Type != right.Type){if (left.Type != typeof(float))left = Expression.Convert(left, typeof(float));if (right.Type != typeof(float))right = Expression.Convert(right, typeof(float));}number.Push(Expression.LessThan(left, right));}break;case "&":if (number.Count > 1){Expression right = number.Pop();Expression left = number.Pop();number.Push(Expression.And(left, right));}break;case "^":if (number.Count > 1){Expression right = number.Pop();Expression left = number.Pop();number.Push(Expression.ExclusiveOr(left, right));}break;case "|":if (number.Count > 1){Expression right = number.Pop();Expression left = number.Pop();number.Push(Expression.Or(left, right));}break;case "=":if (number.Count > 1){Expression right = number.Pop();Expression left = number.Pop();if (left.Type != right.Type){if (left.Type != typeof(float))left = Expression.Convert(left, typeof(float));if (right.Type != typeof(float))right = Expression.Convert(right, typeof(float));}number.Push(Expression.Equal(left, right));}break;case "!":if (number.Count > 1){Expression right = number.Pop();Expression left = number.Pop();if (left.Type != right.Type){if (left.Type != typeof(float))left = Expression.Convert(left, typeof(float));if (right.Type != typeof(float))right = Expression.Convert(right, typeof(float));}number.Push(Expression.NotEqual(left, right));}break;case "?":if (number.Count > 1){Expression right = number.Pop();Expression left = number.Pop();if (left.Type != right.Type){if (left.Type != typeof(float))left = Expression.Convert(left, typeof(float));if (right.Type != typeof(float))right = Expression.Convert(right, typeof(float));}Expression test = number.Pop();number.Push(Expression.Condition(test, left, right));}break;default:if (expr[0] == '@'){switch (expr.Substring(1).ToUpper()){case "TIME":{Expression<Func<string>> f = () => DateTime.Now.ToShortTimeString();number.Push(f.Body);}goto lab1;case "DATE":{Expression<Func<string>> f = () => DateTime.Now.ToShortDateString();number.Push(f.Body);}goto lab1;case "DATETIME":{Expression<Func<string>> f = () => DateTime.Now.ToString();number.Push(f.Body);}goto lab1;case "APP":{Expression<Func<string>> f = () => AppDomain.CurrentDomain.FriendlyName;number.Push(f.Body);}goto lab1;case "NAME":{Expression<Func<string>> f = () => Environment.MachineName;number.Push(f.Body);}goto lab1;case "PATH":{Expression<Func<string>> f = () => Environment.CurrentDirectory;number.Push(f.Body);}goto lab1;case "USER":{Expression<Func<string>> f = () => Environment.UserName;number.Push(f.Body);}goto lab1;case "REGION":{Expression<Func<string>> f = () => System.Globalization.CultureInfo.CurrentCulture.Name;number.Push(f.Body);}goto lab1;}}object result;if (IsConstant(expr, out result)){number.Push(Expression.Constant(result));}else{number.Push(GetTagExpression(expr));}lab1:break;}}Expression d = number.Pop();return Expression.Lambda(d);}catch (Exception e) { return null; }}MethodInfo _boolinfo = typeof(ExpressionEval).GetMethod("GetBool");MethodInfo _floatinfo = typeof(ExpressionEval).GetMethod("GetFloat");MethodInfo _intinfo = typeof(ExpressionEval).GetMethod("GetInt");MethodInfo _stringinfo = typeof(ExpressionEval).GetMethod("GetString");public Expression GetTagExpression(string tagName){if (_server == null) return Expression.Empty();ITag tag = _server[tagName];switch (tag.Address.VarType){case DataType.BOOL:return Expression.Call(_param1, _boolinfo, Expression.Constant(tagName));case DataType.BYTE:case DataType.WORD:case DataType.SHORT:case DataType.DWORD:case DataType.INT:return Expression.Call(_param1, _intinfo, Expression.Constant(tagName));case DataType.FLOAT:return Expression.Call(_param1, _floatinfo, Expression.Constant(tagName));case DataType.STR:return Expression.Call(_param1, _stringinfo, Expression.Constant(tagName));default:return Expression.Empty();}}public bool GetBool(string tagName){if (_server == null) return false;ITag tag = _server[tagName];switch (tag.Address.VarType){case DataType.BOOL:return tag.Value.Boolean;case DataType.BYTE:return Convert.ToBoolean(tag.Value.Byte);case DataType.WORD:return Convert.ToBoolean(tag.Value.Word);case DataType.SHORT:return Convert.ToBoolean(tag.Value.Int16);case DataType.DWORD:return Convert.ToBoolean(tag.Value.DWord);case DataType.INT:return Convert.ToBoolean(tag.Value.Int32);case DataType.FLOAT:return Convert.ToBoolean(tag.Value.Single);case DataType.STR:return Convert.ToBoolean(tag.ToString());default:return false;}}public float GetFloat(string tagName){if (_server == null) return 0f;ITag tag = _server[tagName];return tag.ScaleToValue(tag.Value);}public int GetInt(string tagName){if (_server == null) return 0;ITag tag = _server[tagName];switch (tag.Address.VarType){case DataType.BOOL:return tag.Value.Boolean ? 1 : 0;case DataType.BYTE:return tag.Value.Byte;case DataType.WORD:return tag.Value.Word;case DataType.SHORT:return tag.Value.Int16;case DataType.DWORD:return (int)tag.Value.DWord;case DataType.INT:return tag.Value.Int32;case DataType.FLOAT:return Convert.ToInt32(tag.Value.Single);case DataType.STR:return int.Parse(tag.ToString());default:return 0;}}public string GetString(string tagName){return _server == null ? null : _server[tagName].ToString();}public int WriteTag(string tagName, object value){if (_server == null || value == null) return -1;ITag tag = _server[tagName];if (tag.Address.VarType == DataType.BOOL || tag.Address.VarType == DataType.STR)return tag.Write(value);else{float temp;string str = value as string;if (str == null) temp = Convert.ToSingle(value);else{if (!float.TryParse(str, out temp))return -1;}return tag.Write(tag.ValueToScale(temp));}}private bool IsConstant(string str, out object value){if (str.Length > 1 & str[0] == '\'' && str[str.Length - 1] == '\''){value = str.Trim('\'');return true;}string upp = str.ToUpper();if (upp == "TRUE"){value = true;return true;}else if (upp == "FALSE"){value = false;return true;}if (_server != null){var tag = _server[upp];if (tag != null){if (!_tagList.Contains(tag))_tagList.Add(tag);value = null;return false;}}int dotcount = 0;for (int i = 0; i < str.Length; i++){char opr = str[i];if (opr < '0' || opr > '9'){if (opr != '.'){value = str;return true;}else{if (dotcount > 0){value = str;return true;}dotcount++;}}}//value = (dotcount == 0 ? int.Parse(str) : float.Parse(str));if (dotcount == 0)value = int.Parse(str);else value = float.Parse(str);return true;}public void Clear(){//_param1 = null;_tagList.Clear();//_tagList = null;}public void Dispose(){_param1 = null;_tagList.Clear();_tagList = null;_boolinfo = _floatinfo = _stringinfo = null;}}[StructLayout(LayoutKind.Sequential)]/// <summary>/// 操作符结构/// </summary>public struct Operator{public char OperatorStack;public byte Level;public Operator(char OperatorStack, byte Level){this.OperatorStack = OperatorStack;this.Level = Level;}}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。