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");
}
}
}
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 { get; set; } /// <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)); } } }
Thank you Jonny.
A nice complete answer from which I"ve learned. :D
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.
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
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