Advice on how to define business rule

Advice on how to define business rule

Old forum URL: forums.lhotka.net/forums/t/10983.aspx


shawndewet posted on Tuesday, December 13, 2011

I have a class that has, inter alia, 7 bool properties.  Each bool property represents a day of the week.  It indicates whether or not that day of the week has been selected, eg, MondayChecked, TuesdayChecked, etc.  In the UI, each day is reprsented by a checkbox.  The business rule I need to apply is that at least one of the days must be selected by the user.  How would I implement this business rule in CSLA 4.1?

JonnyBee replied on Wednesday, December 14, 2011

How do you want to display broken rule?

You could do it with a rule like this in CSLA 4.2.:

    public class AnyBool : Csla.Rules.PropertyRule
    {
        private readonly IPropertyInfo[] _boolProperties;
 
        public AnyBool(IPropertyInfo primaryProperty, params IPropertyInfo[] boolProperties) : base(primaryProperty)
        {
            if (boolProperties == null)
                throw new ArgumentNullException("boolProperties""At least one bool property must be specified.");
 
            _boolProperties = boolProperties;
            InputProperties = InputProperties ?? new List<IPropertyInfo>();
            InputProperties.AddRange(boolProperties);
        }
 
 
        protected override string GetMessage()
        {
            return HasMessageDelegate ? base.GetMessage() : "At least one of the fields {0} must be selected.";
        }
 
        protected override void Execute(RuleContext context)
        {
            if (!context.InputPropertyValues.Any(p => (bool)p.Value))
            {
                string fields = string.Join(",", _boolProperties.Select(p => p.FriendlyName));
                context.AddErrorResult(string.Format(GetMessage(), fields));
            }
        }
    }
Usage: 
      BusinessRules.AddRule(new AnyBool(MondayBoolProperty, MondayBoolProperty, TuesdayBoolProperty, 
          WednesdayBoolProperty, ThursdayBoolProperty, FridayBoolProperty, SaturdayBoolProperty, SundayBoolProperty));

The rule would automatically be checked for when any of the boolProperties are changed as InputProperties is considered dependency by the the 4.2 RuleEngine. The rule would also allow you to override the message string by constant or delegate (supports resource strings).

 For CSLA 4.1 you would have to use:

    public class AnyBool : Csla.Rules.BusinessRule
    {
        private readonly IPropertyInfo[] _boolProperties;
 
        public AnyBool(IPropertyInfo primaryProperty, params IPropertyInfo[] boolProperties) : base(primaryProperty)
        {
            if (boolProperties == null)
                throw new ArgumentNullException("boolProperties""At least one bool property must be specified.");
 
            _boolProperties = boolProperties;
            InputProperties = InputProperties ?? new List<IPropertyInfo>();
            InputProperties.AddRange(boolProperties);
        }
 
        protected override void Execute(RuleContext context)
        {
            if (!context.InputPropertyValues.Any(p => (bool)p.Value))
            {
                string fields = string.Join(",", _boolProperties.Select(p => p.FriendlyName));
                context.AddErrorResult(string.Format("At least one of the fields {0} must be selected.", fields));
            }
        }
    }

And a series of Dependency rules to trigger the rule for each time an input property is changed:

Usage:

      BusinessRules.AddRule(new AnyBool(MondayBoolProperty, MondayBoolProperty, TuesdayBoolProperty, 
          WednesdayBoolProperty, ThursdayBoolProperty, FridayBoolProperty, SaturdayBoolProperty, SundayBoolProperty));
      BusinessRules.AddRule(new Dependency(TuesdayBoolProperty, MondayBoolProperty));
      BusinessRules.AddRule(new Dependency(WednesdayBoolProperty, MondayBoolProperty));
      BusinessRules.AddRule(new Dependency(ThursdayBoolProperty, MondayBoolProperty));
      // and so on ... 

Copyright (c) Marimer LLC