We're working out way through converting to CSLA 4 and so far the biggest (mostly mechanical bit) is getting our business rules converted as per CSLA 4.
In one of Rocky's blog posts regarding the BusinessRules (http://www.lhotka.net/weblog/CSLA4BusinessRulesSubsystem.aspx) it's made clear that the rule class should be immutable or put differently we should not change state of the rule class because (if I understand it correctly) the same class instance is used for all properties.
Is it OK to have a rule class with state - never change it - but have another class instance with different state for another property. Eg.:
Here's the class definition:
private class CropAtMaxLengthMutator : BusinessRule
{
private readonly int _maxLength = 3;
public CropAtMaxLengthMutator( IPropertyInfo primaryProperty, int maxLength ) : base( primaryProperty )
{
// Validate type of property
if ( primaryProperty.Type != typeof( string ) )
throw new ArgumentException( string.Format( "Crop at Maximum Length mutator can only apply to properties of type string. Argument: {0} Type: {1}", primaryProperty.Name, primaryProperty.Type.FullName ), "primaryProperty" );
// Initialise state
_maxLength = maxLength;
InputProperties = new List<IPropertyInfo> { primaryProperty };
}
protected override void Execute( RuleContext context )
{
var propertyValue = (string)context.InputPropertyValues[PrimaryProperty];
context.AddOutValue( PrimaryProperty, propertyValue.MaxLength( _maxLength ) );
}
}
I'm assuming the same rule instance is used for only that property, but not for another and so it's OK (much like the new Csla.Rules.CommonRules.MaxLength(NameProperty, 20)) from CSLA?
Hi,
Yes it's safe to create rules like this with member variables/properties that in previous version (pre 4.x) would be in an EventArgs object.
The only caution is that you MUST view instance fields as immutable once the object is created. Remember that the rule object instance is used across all business objects of a given type. So if you change an instance field while the app is running, you'll affect all business objects of that type from that moment. The bugs caused by such a thing would be hard to find and solve.
It is too bad VB and C# don't have any concept about write-once fields, because that's really what's needed here.
Thanks guys - makes sense!
Say wouldn't the "readonly" field modifier (as per example above) be a useful way to try and protect the state?
It allows you to set it only during initialisation/construction
Yes, the readonly modifier means that you can only assign a value in the constructor (or a default value at declaration) and would protect that value from being changed and a good way to code.
But we also want to support both syntaxes
BusinessRules.AddRule(new InfoMessage(Num1Property, "my info message"));
BusinessRules.AddRule(new InfoMessage(Num1Property) {MessageText = "My info message"});
In the latter version there is unfortunately no possibilty for a write once property in C# or VB.NET.
But - you are safe when using readonly and only set values in the constructor.
Copyright (c) Marimer LLC