I'll probably remove per-instance rules in 4.0.
They were the model in 2.0, but had serious perf/resource issues, which is why I added the per-type concepts. Andres lobbied me to remove per-instance at the time, and I think he was right, but I left them in for "backward compatibility".
They exist as they did in 2.0 though, and really don't address a valid scenario in my view. Clearly almost no one uses them, because if anyone did use them they'd run into the issues you describe - and this is the first complaint I've had in years :)
The right answer, imo, is to create per-type rules that are smart enough to be context-sensitive based on the state of the object. In other words, there's nothing you can do with per-instance rules that you can't do with a smarter per-type rule.
RockfordLhotka:They exist as they did in 2.0 though, and really don't address a valid scenario in my view. Clearly almost no one uses them, because if anyone did use them they'd run into the issues you describe - and this is the first complaint I've had in years :)
The right answer, imo, is to create per-type rules that are smart enough to be context-sensitive based on the state of the object. In other words, there's nothing you can do with per-instance rules that you can't do with a smarter per-type rule.
RockfordLhotka:I'll probably remove per-instance rules in 4.0.
Nooooooo!
Please don't remove them. They may now be edge cases, but they still can serve a purpose. I have a dynamic system where the users create data collection flows. They can add data collection points, number of samples, datatype, etcetera and can set up rules (depending on the actual datatype) such as min/minlength, max/maxlength, and so on.
When the sample business object is instantiated for actual data entry, I use the database stored rule metadata to create and add the instance rules to the business objects. It works great but I do not think that I could do the same thing with the static rules alone. The individual business objects for a 'sample' are the same, but may have different rules in effect based not only on the datatype, but also by the specific type of the item you are collecting data on (hierarchical rules), and they type of measurement.
RockfordLhotka:How do you get around the chicken-and-egg problem in your implementation?
I could move the call to Initialize(), or not do it at all - leaving it to you to do the call if you care (which most people wouldn't).
Either one would be a breaking change for anyone using this niche feature (probably just you two :) ), so may not be worth doing.
RockfordLhotka:I could move the call to Initialize(), or not do it at all - leaving it to you to do the call if you care (which most people wouldn't).
Either one would be a breaking change for anyone using this niche feature (probably just you two :) ), so may not be worth doing.
RockfordLhotka:How do you get around the chicken-and-egg problem in your implementation?
I ignore it! ;-)
I add the rules later in the process.
The rules are added to child objects that are nested down a couple of levels in my object hierarchy. As the child is added to its parent collection I query a read-only collection of rule metadata for the sub-set that match the childs criteria. I then iterate over that subset and attach the rule using a helper method. (IValidation just exposes the Csla.Validation.ValidationRules for the object).
public static void AddDynamicRule(IValidation item, Csla.Core.IPropertyInfo property, Validation.ItemDetailRuleInfo rule) MethodInfo mi = typeof(MyApp.Library.Validation.CommonRules).GetMethod(method, BindingFlags.NonPublic | BindingFlags.Static);
if (mi != null)
if (mi.IsGenericMethod)
mi.MakeGenericMethod(rule.Datatype).Invoke(null, new object[] { item, property, rule });
else
mi.Invoke(null, new object[] { item, property, rule });
}
If a property affecting the rule choice is changed, then I can clear out the rules, and re-add them. The clearing of the rules is carried out by a method that gets down and dirty with reflection:
public static void ClearInstanceRules(this Csla.Validation.ValidationRules item)
{
// get the rule manager
MethodInfo mi = item.GetType().GetMethod("GetInstanceRules", BindingFlags.Instance | BindingFlags.NonPublic);
var ruleManager = mi.Invoke(item, new object[] { true });
// clear the instance rules
PropertyInfo pi = ruleManager.GetType().GetProperty("RulesDictionary", BindingFlags.Instance | BindingFlags.NonPublic);
var dictionary = pi.GetValue(ruleManager, null);
MethodInfo dmi = dictionary.GetType().GetMethod("Clear", BindingFlags.Instance | BindingFlags.Public);
dmi.Invoke(dictionary, null);
// get the broken rules variable and re-set it to null
FieldInfo fi = item.GetType().GetField("_rulesToCheck", BindingFlags.NonPublic | BindingFlags.Instance);
fi.SetValue(item, null);
// get the broken rules variable and re-set it to null
fi = item.GetType().GetField("_brokenRules", BindingFlags.NonPublic | BindingFlags.Instance);
fi.SetValue(item, null);
// recheck the remaining (per-type) rules
item.CheckRules();
}
Fintanv:...If a property affecting the rule choice is changed, then I can clear out the rules, and re-add them...
Copyright (c) Marimer LLC