I've an object that comes in two varieties.
Both varieties use about 50 business rules and they share about 40 of them. I'd like to be able to load up the business rules selectively, based upon a property value, however the business rules are added before any object properties are loaded, that is, during hte intialization of the base class.
Is there a way to load the object first (property values), then add the rules, and then check them?
Just off the top of my head, you could create a base class (inheriting from BusinessBase<T>) and create 2 subclasses, each one overriding AddBusinessRules().
Don't forget to call base.AddBusinessRules()!
The idea behind the rules system is that you'd load the 50 rules, and the rules would be smart enough to adapt to the state of the object.
In other words, rather than making the process of adding rules smarter, make the rules themselves smarter.
Yeah, I was afraid I'd have to do that, but it does seem to be the very best answer.
I agree with Rocky on this for the most part, except that I really did find what I think is a use case for the per instance rules that the per type rules don't handle well at all.
I also found the per-instance rules were added by the base class constructuctor. which as you noted means you can't use property values to decide what rules to add. It turns out, however, that you can add your own instance rules "later" and it works well for the most part.
There are some gotchas, though. If you are using a remote data portal, the rules don't get serialized across with the object. Instead, it calls InitializeBusinessRules() again in OnDeserializedHandler(), so you have to plan for this if it matters in your particular case.
For better or worse however, per-instance rules will not be in CSLA 4. On the upside, the new flexibility in the rules system should allow for "gate rules" - a rule that evaluates whether to allow some other rule to run, thus acting as a gate. It is one application of the broader concept of rule chaining, where one rule can invoke other rules, consolidating the results and returning them to the framework when complete.
^^^^
I think I could safely refactor my current implementation to use a different derived class for the special cases where I need instance rules. I actually know what rules are needed at the time the object is constructed, so this would be a straightforward (if only slightly tedious) transformation.
I tried creating a AddBusinessRulesAfterLoad() method which gets called after the business object is loaded. Inside of that I call base.AddBusinessRules() but for some reason only the first object in the collection gets it's rules loaded.
I have an object that comes in three varieties and share numerous rules. A few years ago I did something like this:
1. Place as many common rules as possible in the base class.
2. Inherit the final type for the 1stBO from the base class and then use code like this:
Protected Overrides Sub AddBusinessRules()
MyBase.AddBusinessRules()
If TypeOf Me Is 2ndBO OrElse TypeOf Me Is 3rdBO Then
'Do not add 1stBO Type rules
Else
'Add more rules here that are just for 1stBO type
End If
End Sub
3. Inherit the 2nd and 3rd BO types from the 1stBO type. Then they can have code like this:
Protected
MyBase.AddBusinessRules()
'Add more rules here that are just for 2nd or 3rd BO types.
End Sub
Notice that by inheriting from the 1st BO type the 2nd and 3rd types get the common rules only. They do not get the rules that are specific to the 1st BO type due to the line that reads: If TypeOf Me Is 2ndBO OrElse TypeOf Me Is 3rdBO Then
This trick worked correctly because it relied on the type of the BO (not the value of a Property which has not been loaded yet.) So these are still per type rules, not Instance rules.
Joe
Copyright (c) Marimer LLC