public MethodInfo BindOperator(UnaryOperator op, Type operandType) { if (operandType == typeof(DBNull)) { return(_unaryOperatorPlaceholder); } try { List <MethodInfo> methodList = new List <MethodInfo>(); // Get user defined operator methodList.AddRange(OperatorMethodCache.GetOperatorMethods(operandType, op)); // Get the operator method from the buitlin ones methodList.AddRange(OperatorMethodCache.GetOperatorMethods(typeof(BuiltInOperators), op)); MethodInfo[] methods = methodList.ToArray(); return(BindMethodInfo(methods, new Type[] { operandType })); } catch (InvocationIsAmbiguousException ex) { _errorReporter.AmbiguousOperator(op, operandType, ex.Method1, ex.Method2); // Avoid cascading errors return(ex.Method1); } }
private MethodInfo GetConversionMethod(CastingOperatorType castingOperatorType, Type sourceType, Type targetType) { MethodInfo targetFromSource; MethodInfo sourceToTarget; // First search the target type for a suitable conversion method. targetFromSource = GetConversionMethod(OperatorMethodCache.GetOperatorMethods(targetType, castingOperatorType), sourceType, targetType); // Secondly search the source type for a suitable conversion method. sourceToTarget = GetConversionMethod(OperatorMethodCache.GetOperatorMethods(sourceType, castingOperatorType), sourceType, targetType); if (sourceToTarget == null && targetFromSource == null) { // Ok, no custom casting operators found. Look in the built-in conversions. return(BuiltInConversions.GetConversion(castingOperatorType, sourceType, targetType)); } else { // Now we might have two possible methods. We found an ambiguous match in that case. if (targetFromSource != sourceToTarget && targetFromSource != null && sourceToTarget != null) { // Ambiguous match, we don't know what to do. _errorReporter.AmbiguousOperator(castingOperatorType, targetFromSource, sourceToTarget); return(targetFromSource); } if (targetFromSource != null) { return(targetFromSource); } else { return(sourceToTarget); } } }
public MethodInfo BindOperator(BinaryOperator op, Type leftOperandType, Type rightOperandType) { if (leftOperandType == typeof(DBNull) || rightOperandType == typeof(DBNull)) { return(_binaryOperatorPlaceholder); } MethodInfo result; try { List <MethodInfo> methodList = new List <MethodInfo>(); // Get the operator method from left... methodList.AddRange(OperatorMethodCache.GetOperatorMethods(leftOperandType, op)); if (leftOperandType != rightOperandType) { List <Type> declaringTypes = new List <Type>(); foreach (MethodInfo info in methodList) { if (!declaringTypes.Contains(info.DeclaringType)) { declaringTypes.Add(info.DeclaringType); } } foreach (MethodInfo rightOperatorMethod in OperatorMethodCache.GetOperatorMethods(rightOperandType, op)) { if (!declaringTypes.Contains(rightOperatorMethod.DeclaringType)) { methodList.Add(rightOperatorMethod); } } } // ...from the builtin ones. methodList.AddRange(OperatorMethodCache.GetOperatorMethods(typeof(BuiltInOperators), op)); // Perform overload resolution. MethodInfo[] methods = methodList.ToArray(); result = BindMethodInfo(methods, new Type[] { leftOperandType, rightOperandType }); } catch (InvocationIsAmbiguousException ex) { _errorReporter.AmbiguousOperator(op, leftOperandType, rightOperandType, ex.Method1, ex.Method2); // Avoid cascading errors result = ex.Method1; } // Due to the lack of generic operator methods we have to manually some rules here. // // 1. = and <>. There exists an operator method op_X(object, object) that would allow // comparing any type to any other type. This is not correct. We want to enforce // that both type are compatible (or if any operand is an interface). // 2. & and | for enums. There exists an operator method op_X(Enum, Enum) that would allow // combining any enum with any other enum. This is not correct. We want to enforce // that both enums are the same. if (result == _generalEqualityOperator || result == _generalInequalityOperator) { if (!leftOperandType.IsAssignableFrom(rightOperandType) && !rightOperandType.IsAssignableFrom(leftOperandType) && !leftOperandType.IsInterface && !rightOperandType.IsInterface) { return(null); } } else if (result == _enumBitAndOperator || result == _enumBitOrOperator) { if (leftOperandType != rightOperandType) { return(null); } } return(result); }