Example #1
0
        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);
            }
        }
Example #2
0
        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);
                }
            }
        }
Example #3
0
        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);
        }