private static void AddLiftedOperators(Type type, string methodName, OperatorGrouping group, Type arg1, Type arg2, List<MethodInfo> candidates) { int num = 0; foreach (MethodInfo info in type.GetMethods(BindingFlags.Public | BindingFlags.Static)) { ParameterInfo[] parameters = info.GetParameters(); if ((info.Name == methodName) && (parameters.Length == 2)) { MethodInfo item = EvaluateLiftedMethod(info, parameters, group, arg1, arg2); if (item != null) { num++; if (!candidates.Contains(item)) { candidates.Add(item); } } } } if ((num <= 0) && (type != typeof(object))) { type = type.BaseType; if (type != null) { foreach (MethodInfo info3 in type.GetMethods(BindingFlags.Public | BindingFlags.Static)) { ParameterInfo[] infoArray3 = info3.GetParameters(); if ((info3.Name == methodName) && (infoArray3.Length == 2)) { MethodInfo info4 = EvaluateLiftedMethod(info3, infoArray3, group, arg1, arg2); if ((info4 != null) && !candidates.Contains(info4)) { candidates.Add(info4); } } } } } }
private static MethodInfo EvaluateLiftedMethod(MethodInfo mi, ParameterInfo[] parameters, OperatorGrouping group, Type arg1, Type arg2) { Type parm1 = parameters[0].ParameterType; Type parm2 = parameters[1].ParameterType; if (ConditionHelper.IsNonNullableValueType(parm1) && ConditionHelper.IsNonNullableValueType(parm2)) { // lift the parameters for testing conversions, if possible parm1 = typeof(Nullable<>).MakeGenericType(parm1); parm2 = typeof(Nullable<>).MakeGenericType(parm2); switch (group) { case OperatorGrouping.Equality: // for == != if (mi.ReturnType == typeof(bool) && RuleValidation.ImplicitConversion(arg1, parm1) && RuleValidation.ImplicitConversion(arg2, parm2)) { return new LiftedEqualityOperatorMethodInfo(mi); } break; case OperatorGrouping.Relational: // for < > <= >= if (mi.ReturnType == typeof(bool) && RuleValidation.ImplicitConversion(arg1, parm1) && RuleValidation.ImplicitConversion(arg2, parm2)) { return new LiftedRelationalOperatorMethodInfo(mi); } break; case OperatorGrouping.Arithmetic: // for + - * / % & ^ if (ConditionHelper.IsNonNullableValueType(mi.ReturnType) && RuleValidation.ImplicitConversion(arg1, parm1) && RuleValidation.ImplicitConversion(arg2, parm2)) { return new LiftedArithmeticOperatorMethodInfo(mi); } break; } } return null; }
private static void AddLiftedOperators(Type type, string methodName, OperatorGrouping group, Type arg1, Type arg2, List<MethodInfo> candidates) { // append the list of lifted methods that match the name specified int numAdded = 0; MethodInfo[] possible = type.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo mi in possible) { ParameterInfo[] parameters = mi.GetParameters(); if ((mi.Name == methodName) && (parameters.Length == 2)) { MethodInfo liftedMethod = EvaluateLiftedMethod(mi, parameters, group, arg1, arg2); if (liftedMethod != null) { ++numAdded; if (!candidates.Contains(liftedMethod)) candidates.Add(liftedMethod); } } } if ((numAdded > 0) || (type == typeof(object))) return; // no matches, check direct base class (if there is one) type = type.BaseType; if (type != null) { possible = type.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo mi in possible) { ParameterInfo[] parameters = mi.GetParameters(); if ((mi.Name == methodName) && (parameters.Length == 2)) { MethodInfo liftedMethod = EvaluateLiftedMethod(mi, parameters, group, arg1, arg2); if ((liftedMethod != null) && !candidates.Contains(liftedMethod)) candidates.Add(liftedMethod); } } } }
private static MethodInfo EvaluateLiftedMethod(MethodInfo mi, ParameterInfo[] parameters, OperatorGrouping group, Type arg1, Type arg2) { Type parameterType = parameters[0].ParameterType; Type type = parameters[1].ParameterType; if (ConditionHelper.IsNonNullableValueType(parameterType) && ConditionHelper.IsNonNullableValueType(type)) { parameterType = typeof(Nullable<>).MakeGenericType(new Type[] { parameterType }); type = typeof(Nullable<>).MakeGenericType(new Type[] { type }); switch (group) { case OperatorGrouping.Arithmetic: if ((!ConditionHelper.IsNonNullableValueType(mi.ReturnType) || !RuleValidation.ImplicitConversion(arg1, parameterType)) || !RuleValidation.ImplicitConversion(arg2, type)) { break; } return new LiftedArithmeticOperatorMethodInfo(mi); case OperatorGrouping.Equality: if ((!(mi.ReturnType == typeof(bool)) || !RuleValidation.ImplicitConversion(arg1, parameterType)) || !RuleValidation.ImplicitConversion(arg2, type)) { break; } return new LiftedEqualityOperatorMethodInfo(mi); case OperatorGrouping.Relational: if ((!(mi.ReturnType == typeof(bool)) || !RuleValidation.ImplicitConversion(arg1, parameterType)) || !RuleValidation.ImplicitConversion(arg2, type)) { break; } return new LiftedRelationalOperatorMethodInfo(mi); } } return null; }