private Result CreateResult(Rule rule, ResultStatus status, FailureReason reason, object left, RuleComparisonOperatorParameter.Operator op, object right, params ResultDetail[] details) { Result result = new Result(this, rule, status, reason, String.Format(CultureInfo.CurrentCulture, rule.ErrorInfoTemplate, left, RuleComparisonOperatorParameter.StringForOperator(op), right)); foreach (ResultDetail detail in details) { result.Details.Add(detail); } return(result); }
protected override IEnumerable <Result> CheckInternal(object checkable, Rule rule) { object leftValue = GetValue(checkable, (rule.Parameters["LeftValueFieldName"] as RuleStringParameter).Value); RuleComparisonOperatorParameter.Operator comparisonOperator = (rule.Parameters["ComparisonOperator"] as RuleComparisonOperatorParameter).Value; var extractionClassParameter = rule.Parameters["ExtractionFunctionClass"] as RuleStringParameter; var extractionFunctionParameter = rule.Parameters["ExtractionFunctionName"] as RuleStringParameter; MethodInfo extractionFunction = null; // simple check here, more elaborate check is being done in IsCompatibleParameterSet if (extractionClassParameter != null) { var extractionClassType = Type.GetType(extractionClassParameter.Value); if (extractionClassType == null) { yield return(new Result(this, rule, ResultStatus.Fail, FailureReason.CheckNotPerformed, "Extraction class not found")); yield break; } extractionFunction = extractionClassType.GetMethod(extractionFunctionParameter.Value); if (extractionFunction == null) { yield return(new Result(this, rule, ResultStatus.Fail, FailureReason.CheckNotPerformed, "Extraction function not found")); yield break; } // No yield returning in the body of a catch clause. Great. // I'll just do it myself then. Exception leftValueException = null; try { leftValue = extractionFunction.Invoke(null, new object[] { leftValue }); } catch (Exception ex) { leftValueException = ex; } if (leftValueException != null) { yield return(new Result(this, rule, ResultStatus.Fail, FailureReason.CheckNotPerformed, "Extraction function call failed for left value: " + leftValueException.Message)); yield break; } } object rightValue; var rightValueParameter = rule.Parameters["RightValue"]; if (rightValueParameter != null) { rightValue = rightValueParameter.Value; } else { rightValue = GetValue(checkable, (rule.Parameters["RightValueFieldName"] as RuleStringParameter).Value); Exception rightValueException = null; if (extractionFunction != null) { try { rightValue = extractionFunction.Invoke(null, new object[] { rightValue }); } catch (Exception ex) { rightValueException = ex; } if (rightValueException != null) { yield return(new Result(this, rule, ResultStatus.Fail, FailureReason.CheckNotPerformed, "Extraction function call failed for right value: " + rightValueException.Message)); yield break; } } } if (rightValue == null) { if (leftValue == null) { yield return(new Result(this, rule, ResultStatus.Pass, FailureReason.None, String.Empty)); } else { yield return(CreateResult(rule, ResultStatus.Fail, FailureReason.CheckFailed, leftValue, comparisonOperator, rightValue)); } yield break; } // I wouldn't initialize this at all, because the following lines // of code ensure that compResult is initialized before it reaches // the switch block below, or otherwise the method quits. // But the compiler doesn't understand this due to the added // complexity with the exception handling. int compResult = 0; Exception comparisonException = null; try { compResult = Comparer.Default.Compare(leftValue, rightValue); } catch (Exception ex) { comparisonException = ex; } if (comparisonException != null) { yield return(CreateResult(rule, ResultStatus.Fail, FailureReason.CheckNotPerformed, leftValue, comparisonOperator, rightValue, new ResultDetail("ExceptionMessage", comparisonException.Message))); yield break; } bool compResultB = false; switch (comparisonOperator) { case RuleComparisonOperatorParameter.Operator.Smaller: compResultB = compResult < 0; break; case RuleComparisonOperatorParameter.Operator.SmallerOrEqual: compResultB = compResult <= 0; break; case RuleComparisonOperatorParameter.Operator.Equal: compResultB = compResult == 0; break; case RuleComparisonOperatorParameter.Operator.NotEqual: compResultB = compResult != 0; break; case RuleComparisonOperatorParameter.Operator.GreaterOrEqual: compResultB = compResult >= 0; break; case RuleComparisonOperatorParameter.Operator.Greater: compResultB = compResult > 0; break; } if (compResultB) { yield return(new Result(this, rule, ResultStatus.Pass, FailureReason.None, null)); } else { yield return(CreateResult(rule, ResultStatus.Fail, FailureReason.CheckFailed, leftValue, comparisonOperator, rightValue)); } }