private TempComputeResult ComputeCustomConditionalLogic(Type type, string methodXName, string methodYName, object leftValue, object rightValue) { var methodX = DebugService.GetMethod(type, methodXName, BindingFlags.Public | BindingFlags.Static, methodInfo => CheckConditionalOperatorUnaryMethodParameters(type, methodInfo)); if (methodX == null) { return(null); } var methodY = DebugService.GetMethod(type, methodYName, BindingFlags.Public | BindingFlags.Static, methodInfo => CheckConditionalOperatorBinaryMethodParameters(type, methodInfo)); if (methodY == null) { return(null); } var condition = (bool)methodX.Invoke(null, new object[1] { leftValue }); object obj = leftValue; if (!condition) { obj = methodY.Invoke(null, new object[2] { leftValue, rightValue }); } return(CreateComputeResult(obj, type)); }
public override TempComputeResult VisitBinaryExpression(BinaryExpressionSyntax node) { var left = Visit(node.Left); var right = Visit(node.Right); var operatorText = node.OperatorToken.Text; if (left.Type == null && right.Type == null) { if (operatorText == "==") { return(CreateComputeResult(true, typeof(bool))); } else { return(CreateComputeResult(null, null)); } } var leftType = left.Type; var rightType = right.Type; string methodName; if (dic_BinaryOperator_MethodName.TryGetValue(operatorText, out methodName)) { var bindingFlags = BindingFlags.Public | BindingFlags.Static; var overloadOperatorMethod = DebugService.GetMethod(leftType, methodName, bindingFlags, true, leftType, rightType); if (overloadOperatorMethod == null) { overloadOperatorMethod = DebugService.GetMethod(rightType, methodName, bindingFlags, true, leftType, rightType); } if (overloadOperatorMethod != null) // 有运算符重载 { var result = overloadOperatorMethod.Invoke(null, new object[2] { left.Value, right.Value }); return(CreateComputeResult(result, overloadOperatorMethod.ReturnType)); } else { return(ComputeBinaryNative(leftType, rightType, left.Value, right.Value, operatorText, node)); } } else { var result = ComputeCustomConditionalLogicOperator(leftType, rightType, left.Value, right.Value, operatorText); // 用户定义的条件逻辑运算符,规则为https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/language-specification/expressions#conditional-logical-operators if (result != null) { return(result); } return(ComputeBinaryNative(leftType, rightType, left.Value, right.Value, operatorText, node)); //throw new NotSupportedException("Unknown Binary Operator:" + operatorText); } }
public override TempComputeResult VisitConditionalExpression(ConditionalExpressionSyntax node) { var tuple = GetOrCreateVariableReference(node, ""); tuple.Top.Type = VariableTypes.Value; bool conditionValue; var conditionResult = Visit(node.Condition); if (conditionResult.Value is bool) { conditionValue = (bool)conditionResult.Value; } else { // true运算符重载 var overloadTrueMethod = DebugService.GetMethod(conditionResult.Type, "op_True", BindingFlags.Public | BindingFlags.Static, methodInfo => CheckConditionalOperatorUnaryMethodParameters(conditionResult.Type, methodInfo)); if (overloadTrueMethod != null) { conditionValue = (bool)overloadTrueMethod.Invoke(null, new object[1] { conditionResult.Value }); } else { throw new InvalidOperationException(string.Format("\"{0}\" is not conditional expression", node.Condition.ToString())); } } TempComputeResult result; if (conditionValue) { result = Visit(node.WhenTrue); } else { result = Visit(node.WhenFalse); } tuple.Top.Value = result.Value; tuple.Top.ValueType = result.Type; return(ResolveVariable(tuple.Bottom)); }
public TempComputeResult VisitUnaryExpression(ExpressionSyntax operand, string operatorText, bool isPrefix, string nodeText) { var operandResult = Visit(operand); if (operandResult.Type == null) { return(CreateComputeResult(null, null)); } string methodName; if (dic_UnaryOperator_MethodName.TryGetValue(operatorText, out methodName)) { var bindingFlags = BindingFlags.Public | BindingFlags.Static; var overloadOperatorMethod = DebugService.GetMethod(operandResult.Type, methodName, bindingFlags, true, operandResult.Type); if (overloadOperatorMethod != null) // 有运算符重载 { var result = overloadOperatorMethod.Invoke(null, new object[1] { operandResult.Value }); return(CreateComputeResult(result, overloadOperatorMethod.ReturnType)); } } try { var expressionText = isPrefix ? "{0}x" : "x{0}"; var func = new DynamicExpresso.Interpreter().Parse(string.Format(expressionText, operatorText), new DynamicExpresso.Parameter("x", operandResult.Type.UnWrapper())); var result = func.Invoke(operandResult.Value); return(CreateComputeResult(result, result == null ? null : result.GetType())); } catch { throw new Exception(string.Format("Fail to calculate '{0}'", nodeText)); } }