I've been wondering about this. From what I gather, the current possible approach is to register a property using a RelationshipTypes.PrivateField, but in reality there's no private field.
For instance, an invoice with line items.
Public ReadOnly Property TotalAmount As Decimal
Return LineItems.Sum(Function(o) o.Amount)
Typically you might want to add a >0 rule for this property and have the ui report it, against that property. I understand you could create an object rule, but then you lose the visual cue on the bound label in a potential form.
I think that creating a property info for this is overkill, considering there's no independent backing data for it and the fact that a data annotation should normally work for this scenario (haven't yet tested it in csla though, but not sure it would work).
I was wondering, if rules could be extended to take a lambda as well (take an IPropertyInfo OR a Lambda), this wouldn't require the unnecessary propertyinfo. Plus, if there were a property info matching that lambda, it could very well be retrieved internally by the rule system. This would make business rules much more flexible. If absolutely necessary, the Rule code could even create and add the propertyinfo behind the scenes. Or is it absolutely necessary to have that propertyinfo declared in code?
In the end you'd end up doing something like:
BusinessRules.AddRule(New Lambda(Function(obj) obj.TotalAmount, Sub(o)
If DirectCast(o.Target, Invoice).TotalAmount <= 0 Then
o.AddErrorResult("Value can't be zero")
On another subject, it'd be nice to have another Lambda rule that takes object type and primary property type generic arguments. Then target could be typed and an extra property called "PrimaryPropertyValue" could be added.
As usual, I'd be more than glad to help with the implementation of something like this.
I've been updating the rules engine for the next release of Csla so that you may create object rules and property level rules that can set error/warn/info on another property. You must however create an IPropertyInfo object for that property and allow an empty data slot in managed properties but would be an alternative.
BTW: If you are going to use the Csla Rule engine you MUST have an IPropertyInfo object as this is the key for rule result of all property level rules (or null for object level rules).
Hi JonnyBee, Thanks for your input.
Anyway, that's what I'm getting at, if the key were changed to something that allows more flexibility (Reflection.PropertyInfo or even the name, considering the IComparable implementation for propertyinfo uses the name anyway) you wouldn't need to register a property when there's really no need.
As I said, another possibility would be (if it's absolutely needed) to create the property info behind the scenes if it doesn't exist.
Would a data annotation rule work if there's no propertyinfo? would it throw an exception? From looking at AddDataAnnotations() it looks like it would just throw an exception, because it won't find the property in the managed properties list (this should probably be revised to throw a more meaningful exception btw).
I'm evaluating the cost of migration for a 2.1 app to the latest version and these things really add a lot of work to the mix. Please don't get me wrong, I really value the improvements that have been made in terms of validation, I just think a little more flexibility would be great. The same goes for PropertyHasChanged, where I don't see any reason for not supporting a string anymore or even a lambda.
Yes, adding DataAnnotations to properties without PropertyInfo will throw exception.
I believe there are several reasons:
A. In order to use the "automatic" serialization for SL / WP you must use PropertyInfo on each valuetype/child property. If not you must add code for OngetState/OnSetState/OnGetChildren/OnSetChildren IE: PropertyInfo is required for the MobileFormatter/IMobileObject for serialization/deserialization in SL and WP.
B. BusinessRules require IPropertyInfo.
C. BusinessRules are registered per type. No more instance rules.
PropertyHasChanged will mark the object as dirty and run BusinessRules for that property.If you look at the internal function there is still a private PropertyHasChanged(string propertyName) but this method requires that a IPropertyInfo is registered for the type with the propertyname.
You may still use OnPropertyChanged(string propertyName) to notify UI of a change.
Thanks again Jonny for your reply.
A. Remember, I'm talking about a calculated property, so there's no backing data and no issue with serialization.
B. I'm aware of this, which is why I'm raising the subject on whether this could be opened up for more flexibility.
C. This is not about instance rules either.
The fact that PropertyHasChanged marks the object as dirty doesn't change anything, since you may want still want to mark the object dirty (even if the property is calculated) or just check rules or just notify the ui. We've lost the ability to do that and a lot of the control we used to have. The problem I see is that while I like the new features a lot, there are a lot of new limitations on what you can do, some of which seem to be imposed by silverlight. It's sad that we've lost that much flexibility and it should really be up to the user to do extra work to support a platform or not. Specially when you still have to do extra coding and conditional compiling for that platform anyway.
Copyright (c) Marimer LLC