CSLA 4.0 Generic Business Rule

CSLA 4.0 Generic Business Rule

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


MadGerbil posted on Tuesday, June 28, 2011

I'd like to write a business rule that compares two date values on an object to make sure one date occurs on or before the other date.   I don't understand how to make this generic though.  The best thing I can come up with is a pertype implementation.   Any ideas on how to make this generic so that I can use it on serveral types?

public class DateOrder : Csla.Rules.BusinessRule
{
      public DateOrder(Csla.Core.IPropertyInfo primaryProperty)
      : base(primaryProperty)
      {
            InputProperties = new List<Csla.Core.IPropertyInfo> { PrimaryProperty };
      }

      protected override void Execute(Csla.Rules.RuleContext context)
      {
            var obj = (MyObject)context.Target;
            if (obj.StartDate > obj.EndDate)
            {
                  context.AddErrorResult(@"Start Date must be less than or equal to the End Date");
            }
      }
}

JonnyBee replied on Tuesday, June 28, 2011

You can find these generic rules in CslaContrib (http://cslacontrib.codeplex.com ) and download the latest source in repository. 
You will find all the standard CSLA rules and additional rules that will also allow you to set your own error message.
 
Usage:
BusinessRules.AddRule(new LessThan(Num1Property, Num2Property) 
                   {ErrorMessageDelegate = () => "Num1 must be less than Num2."});
 
The key is to generic compare rules is to use the IComparable interface:
 
  /// <summary>
  /// Validates that primary property is less than compareToProperty
  /// </summary>
  public class LessThan : CommonBusinessRule
  {
    private IPropertyInfo CompareTo { getset; }
 
    /// <summary>
    /// Initializes a new instance of the <see cref="LessThan"/> class.
    /// </summary>
    /// <param name="primaryProperty">The primary property.</param>
    /// <param name="compareToProperty">The compare to property.</param>
    public LessThan(IPropertyInfo primaryProperty, IPropertyInfo compareToProperty)
      : base(primaryProperty)
    {
      CompareTo = compareToProperty;
      InputProperties = new List<IPropertyInfo> { primaryProperty, compareToProperty };
    }
 
    /// <summary>
    /// Initializes a new instance of the <see cref="LessThan"/> class.
    /// </summary>
    /// <param name="primaryProperty">The primary property.</param>
    /// <param name="compareToProperty">The compare to property.</param>
    /// <param name="errorMessageDelegate">The error message function.</param>
    public LessThan(IPropertyInfo primaryProperty, IPropertyInfo compareToProperty,
                    Func<string> errorMessageDelegate)
      : this(primaryProperty, compareToProperty)
    {
      ErrorMessageDelegate = errorMessageDelegate;
    }
 
    /// <summary>
    /// Gets the error message.
    /// </summary>
    /// <value></value>
    protected override string ErrorMessage
    {
      get
      {
        return HasErrorMessageDelegate ? base.ErrorMessage : CslaContrib.Properties.Resources.LessThanRule;
      }
    }
 
    /// <summary>
    /// Does the check for primary propert less than compareTo property
    /// </summary>
    /// <param name="context">Rule context object.</param>
    protected override void Execute(RuleContext context)
    {
      var value1 = (IComparable)context.InputPropertyValues[PrimaryProperty];
      var value2 = (IComparable)context.InputPropertyValues[CompareTo];
 
      if (value1.CompareTo(value2) >= 0)
      {
        context.AddErrorResult(string.Format(ErrorMessage, PrimaryProperty.FriendlyName, CompareTo.FriendlyName));
      }
    }
  }

MadGerbil replied on Wednesday, June 29, 2011

Thank you Jonny.

A nice complete answer from which I"ve learned.  :D

LeslieE replied on Friday, June 22, 2012

In my case, I'm dealing with a 3rd party application that we now own and are custimizing in-house.  I want to bang out changes as quickly as I can with minimal impact untill I have time to dig in and really learn it.  It is using CSLA 2 and I'm not ready to upgrade it yet because I don't yet have the time to do it.

 I also needed a date compare so here is my hack using CSLA 2 and not requiring me to add classes to my existing code.

//cheating - use pipe delimiter to send two properties

ValidationRules.AddInstanceRule(

WqxWeb.Common.

 

 

ValidationRules

.Date1LessThanTDate2,

 

 

 

new RuleArgs("Date1FieldName|Date2FieldName","Date 1|Date 2"

));

And then parsed the RulesArgs in the ValidationRoutine Date1LessThanDate2(object target,RuleArgs e)

 

string[] eA = e.PropertyName.ToString().Split('|');

 

 

 

string  e1 = eA[0];

string  e2 = eA[1];

eA = e.PropertyFriendlyName.ToString().Split(

 

'|');

 

 

 

string e3 = eA[0];

 

 

 

string e4 = eA[1];

Just my quick hack for now to get the validation in there for starters.  I can't believe the 3rd party vendor who wrote this allows a start date AFTER and end date in the first place. Sigh.

 

JonnyBee replied on Friday, June 22, 2012

Hi,

If you look at this in CslaContrib - you will find generic GreaterThan, GreaterThanOrEqual, LessThan, LessThanOrEqual rules and more.

http://cslacontrib.codeplex.com/SourceControl/changeset/view/98444#1551668

 

tiago replied on Monday, June 25, 2012

Hi,

Have a look at Rules sample v.1.1.0. This library includes CslaContrib rules plus rules from the Csla's RuleTutorial sample.

Copyright (c) Marimer LLC