Example #1
0
        private List <string> RunRules(IEnumerable <IBusinessRule> rules)
        {
            var  affectedProperties = new List <string>();
            bool anyRuleBroken      = false;

            foreach (var rule in rules)
            {
                // implicit short-circuiting
                if (anyRuleBroken && rule.Priority > ProcessThroughPriority)
                {
                    break;
                }
                bool complete = false;
                // set up context
                var context = new RuleContext((r) =>
                {
                    if (r.Rule.IsAsync)
                    {
                        lock (SyncRoot)
                        {
                            // update output values
                            if (r.OutputPropertyValues != null)
                            {
                                foreach (var item in r.OutputPropertyValues)
                                {
                                    ((IManageProperties)_target).LoadProperty(item.Key, item.Value);
                                }
                            }
                            // update broken rules list
                            if (r.Results != null)
                            {
                                foreach (var result in r.Results)
                                {
                                    BrokenRules.SetBrokenRule(result);
                                }
                            }

                            // mark each property as not busy
                            foreach (var item in r.Rule.AffectedProperties)
                            {
                                BusyProperties.Remove(item);
                                _isBusy = BusyProperties.Count > 0;
                                if (!BusyProperties.Contains(item))
                                {
                                    _target.RuleComplete(item);
                                }
                            }
                            if (!RunningRules && !RunningAsyncRules)
                            {
                                _target.AllRulesComplete();
                            }
                        }
                    }
                    else // Rule is Sync
                    {
                        // update output values
                        if (r.OutputPropertyValues != null)
                        {
                            foreach (var item in r.OutputPropertyValues)
                            {
                                ((IManageProperties)_target).LoadProperty(item.Key, item.Value);
                            }
                        }
                        // update broken rules list
                        if (r.Results != null)
                        {
                            foreach (var result in r.Results)
                            {
                                BrokenRules.SetBrokenRule(result);
                            }
                            // is any rules here broken with severity Error
                            if (r.Results.Where(p => !p.Success && p.Severity == RuleSeverity.Error).Any())
                            {
                                anyRuleBroken = true;
                            }
                        }

                        complete = true;
                    }
                });
                context.Rule = rule;
                if (!rule.IsAsync || rule.ProvideTargetWhenAsync)
                {
                    context.Target = _target;
                }

                // get input properties
                if (rule.InputProperties != null)
                {
                    var target = _target as Core.IManageProperties;
                    context.InputPropertyValues = new Dictionary <IPropertyInfo, object>();
                    foreach (var item in rule.InputProperties)
                    {
                        context.InputPropertyValues.Add(item, target.ReadProperty(item));
                    }
                }

                // mark properties busy
                if (rule.IsAsync)
                {
                    lock (SyncRoot)
                    {
                        // mark each property as busy
                        foreach (var item in rule.AffectedProperties)
                        {
                            var alreadyBusy = BusyProperties.Contains(item);
                            BusyProperties.Add(item);
                            _isBusy = true;
                            if (!alreadyBusy)
                            {
                                _target.RuleStart(item);
                            }
                        }
                    }
                }

                // execute (or start executing) rule
                try
                {
                    rule.Execute(context);
                }
                catch (Exception ex)
                {
                    context.AddErrorResult(string.Format("{0}:{1}", rule.RuleName, ex.Message));
                    if (rule.IsAsync)
                    {
                        context.Complete();
                    }
                }

                if (!rule.IsAsync)
                {
                    // process results
                    if (!complete)
                    {
                        context.Complete();
                    }
                    // copy affected property names
                    affectedProperties.AddRange(rule.AffectedProperties.Select(c => c.Name));
                    // copy output property names
                    if (context.OutputPropertyValues != null)
                    {
                        affectedProperties.AddRange(context.OutputPropertyValues.Select(item => item.Key.Name));
                    }
                    if (context.Results != null)
                    {
                        // explicit short-circuiting
                        if (context.Results.Where(r => r.StopProcessing).Any())
                        {
                            break;
                        }
                    }
                }
            }
            // return any synchronous results
            return(affectedProperties);
        }