public RunRulesStatus <bool> RunRules <T>(IEnumerable <RuleAppliedBase> rules, ref T input,
                                                  RunRulesParameters <T, bool> runParameters)
        {
            var ret = new RunRulesStatus <bool> {
                RulesStatus = new Dictionary <int, RunRuleStatus>()
            };

            ret.LastRunStatistics.ObjectsRun++;

            var sw = new Stopwatch();

            foreach (RuleAppliedBase ruleAppliedBase in rules.OrderBy(c => c.ApplyOrder).ThenBy(c => c.RuleAppliedId))
            {
                sw.Start();
                try
                {
                    if (ruleAppliedBase.ConditionCodeId != null)
                    {
                        if (!runParameters.CondFuncs[ruleAppliedBase.ConditionCodeId.Value].Invoke(input))
                        {
                            continue;
                        }
                    }

                    ret.LastRunStatistics.TotalRulesRun++;

                    ret.RulesStatus.Add(ruleAppliedBase.RuleAppliedId,
                                        new RunRuleStatus()
                    {
                        Exceptions = null, CompletionStatus = RunRuleCompletionStatus.Completed
                    });
                    ret.Result = runParameters.RuleFuncs[ruleAppliedBase.CodeId].Invoke(input);
                }
                catch (Exception ex)
                {
                    var tempRunRuleStat = new RunRuleStatus
                    {
                        Exceptions = new List <Exception> {
                            ex
                        },
                        CompletionStatus = RunRuleCompletionStatus.Failed
                    };

                    var iEx = ex.InnerException;
                    while (iEx != null)
                    {
                        tempRunRuleStat.Exceptions.Add(iEx);
                        iEx = iEx.InnerException;
                    }

                    ret.RulesStatus.Add(ruleAppliedBase.RuleAppliedId, tempRunRuleStat);
                }
                sw.Stop();
                sw.Reset();
                ret.LastRunStatistics.TotalRunTime += sw.Elapsed;

                //did rule have an exception? are we supposed to quit if we hit excpetions?
                if (ret.RulesStatus[ruleAppliedBase.RuleAppliedId].HasException &&
                    !runParameters.ContinueRunningAfterException)
                {
                    break;
                }

                //did we get a true result? are we supposed to run until we hit the first code that returns true?
                if (ret.Result && runParameters.RunUntilFirstRuleHit)
                {
                    break;
                }
            }

            _ongoingRuleStats.ObjectsRun    += ret.LastRunStatistics.ObjectsRun;
            _ongoingRuleStats.TotalRulesRun += ret.LastRunStatistics.TotalRulesRun;
            _ongoingRuleStats.TotalRunTime  += ret.LastRunStatistics.TotalRunTime;

            ret.GlobalRunStatistics = _ongoingRuleStats;

            return(ret);
        }
        public RunRulesStatus <Tout> RunRules <Tin, Tout>(IEnumerable <RuleAppliedBase> rules, ref Tin input,
                                                          RunRulesParameters <Tin, Tout> runParameters)
        {
            var ret = new RunRulesStatus <Tout> {
                RulesStatus = new Dictionary <int, RunRuleStatus>()
            };

            ret.LastRunStatistics.ObjectsRun++;

            var sw = new Stopwatch();

            foreach (RuleAppliedBase ruleAppliedBase in rules.OrderBy(c => c.ApplyOrder).ThenBy(c => c.RuleAppliedId))
            {
                sw.Start();
                try
                {
                    if (ruleAppliedBase.ConditionCodeId != null)
                    {
                        if (!runParameters.CondFuncs[ruleAppliedBase.ConditionCodeId.Value].Invoke(input))
                        {
                            continue;
                        }
                    }

                    ret.LastRunStatistics.TotalRulesRun++;

                    ret.RulesStatus.Add(ruleAppliedBase.RuleAppliedId,
                                        new RunRuleStatus()
                    {
                        Exceptions = null, CompletionStatus = RunRuleCompletionStatus.Completed
                    });
                    ret.Result = runParameters.RuleFuncs[ruleAppliedBase.CodeId].Invoke(input);
                }
                catch (Exception ex)
                {
                    var tempRunRuleStat = new RunRuleStatus
                    {
                        Exceptions = new List <Exception> {
                            ex
                        },
                        CompletionStatus = RunRuleCompletionStatus.Failed
                    };

                    Exception iEx = ex.InnerException;
                    while (iEx != null)
                    {
                        tempRunRuleStat.Exceptions.Add(iEx);
                        iEx = iEx.InnerException;
                    }

                    if (ret.RulesStatus.ContainsKey(ruleAppliedBase.RuleAppliedId))
                    {
                        ret.RulesStatus[ruleAppliedBase.RuleAppliedId] = tempRunRuleStat;
                    }
                    else
                    {
                        ret.RulesStatus.Add(ruleAppliedBase.RuleAppliedId, tempRunRuleStat);
                    }
                }
                sw.Stop();
                sw.Reset();
                ret.LastRunStatistics.TotalRunTime += sw.Elapsed;

                if (ret.RulesStatus[ruleAppliedBase.RuleAppliedId].HasException &&
                    !runParameters.ContinueRunningAfterException)
                {
                    break;
                }
            }

            _ongoingRuleStats.ObjectsRun    += ret.LastRunStatistics.ObjectsRun;
            _ongoingRuleStats.TotalRulesRun += ret.LastRunStatistics.TotalRulesRun;
            _ongoingRuleStats.TotalRunTime  += ret.LastRunStatistics.TotalRunTime;

            ret.GlobalRunStatistics = _ongoingRuleStats;

            return(ret);
        }
        public RunRulesStatus <T> RunRules <T>(List <RuleAppliedBase> rules, ref T input,
                                               RunRulesParameters <T, T> runParameters)
        {
            var ret = new RunRulesStatus <T> {
                RulesStatus = new Dictionary <int, RunRuleStatus>()
            };

            ret.LastRunStatistics.ObjectsRun++;

            T runningInput = input;

            var sw = new Stopwatch();

            foreach (RuleAppliedBase ruleAppliedBase in rules.OrderBy(c => c.ApplyOrder).ThenBy(c => c.RuleAppliedId))
            {
                sw.Start();
                try
                {
                    if (ruleAppliedBase.ConditionCodeId != null)
                    {
                        if (!runParameters.CondFuncs[ruleAppliedBase.ConditionCodeId.Value].Invoke(input))
                        {
                            continue;
                        }
                    }

                    ret.LastRunStatistics.TotalRulesRun++;

                    ret.RulesStatus.Add(ruleAppliedBase.RuleAppliedId,
                                        new RunRuleStatus()
                    {
                        Exceptions = null, CompletionStatus = RunRuleCompletionStatus.Completed
                    });
                    ret.Result = runParameters.RuleFuncs[ruleAppliedBase.CodeId].Invoke(runningInput);

                    //since the input/output is the same, make sure we set the running input and the actualy input to the result of the rule
                    //this will do 2 things
                    //1) ensure the input is updated and passed to the subseqeunt rule call
                    //2) ensure if the in put is checked by the caller, it is updated to match the result that we are passing out - this should be the case anyway, but ew want to enforce it
                    runningInput = ret.Result;
                    input        = ret.Result;
                }
                catch (Exception ex)
                {
                    var tempRunRuleStat = new RunRuleStatus
                    {
                        CompletionStatus = RunRuleCompletionStatus.Failed
                    };

                    var iEx = ex.InnerException;
                    while (iEx != null)
                    {
                        tempRunRuleStat.Exceptions.Add(iEx);
                        iEx = iEx.InnerException;
                    }

                    ret.RulesStatus[ruleAppliedBase.RuleAppliedId] = tempRunRuleStat;
                }

                sw.Stop();
                sw.Reset();
                ret.LastRunStatistics.TotalRunTime += sw.Elapsed;

                if (ret.RulesStatus[ruleAppliedBase.RuleAppliedId].HasException &&
                    !runParameters.ContinueRunningAfterException)
                {
                    break;
                }
            }

            _ongoingRuleStats.ObjectsRun    += ret.LastRunStatistics.ObjectsRun;
            _ongoingRuleStats.TotalRulesRun += ret.LastRunStatistics.TotalRulesRun;
            _ongoingRuleStats.TotalRunTime  += ret.LastRunStatistics.TotalRunTime;

            ret.GlobalRunStatistics = _ongoingRuleStats;

            return(ret);
        }