I have a property that required some custom behaviour in the setter:
I need to set another property bases on the new value, and delay rule checking until both properties are set. NB: all rules are triggered by PrimaryContactId, not PrimaryContact,
Here is my code:
public static readonly PropertyInfo PrimaryContactIdProperty = RegisterProperty(c => c.PrimaryContactId);
public int PrimaryContactId
{
get { return GetProperty(PrimaryContactIdProperty); }
}
public static readonly PropertyInfo PrimaryContactProperty = RegisterProperty(c => c.PrimaryContact, RelationshipTypes.Child | RelationshipTypes.LazyLoad);
public IContact PrimaryContact
{
get
{
if (!FieldManager.FieldExists(PrimaryContactProperty))
{
LoadProperty(PrimaryContactProperty, ContactLoader.Get(this.PrimaryContactId));
OnPropertyChanged(PrimaryContactProperty);
}
return GetProperty(PrimaryContactProperty);
}
set
{
CanWriteProperty(PrimaryContactIdProperty, true); // Execute any authorization rules on PrimaryContactId
OnPropertyChanging(PrimaryContactIdProperty);
LoadProperty(PrimaryContactIdProperty, value != null ? value.Id : -1);
LoadProperty(PrimaryContactProperty, value);
PropertyHasChanged(PrimaryContactIdProperty); // Execute any property rules on PrimaryContactId
}
}
This results in my Business object being marked as dirty, but the PrimaryContactIdProperty itself is not marker as dirty, so it isn't updated.
Lookig through the source I see that "FieldManager.SetFieldData<P>(propertyInfo, newValue);" is used by SetProperty to mark updated fields as dirty. Unfortunately thes is an internal method :(.
What can I do?
Change your setter code to:
set
{
CanWriteProperty(PrimaryContactIdProperty, true); // Execute any authorization rules on PrimaryContactId
OnPropertyChanging(PrimaryContactIdProperty);
LoadProperty(PrimaryContactProperty, value);
SetProperty(PrimaryContactIdProperty, value != null ? value.Id : -1);
}
This is logical, and a correct solution at the moment; but what if I need to assign some rules to PrimaryContact in future? I will need to use load property for both properties. This is my concern because I don't know if there is a solution, other than NOT assigning any rules to PrimaryContact. The problem is that future developers may not know this. So I am trying to come up with a foolproof pattern.
In general terms - my coding preference is to keep ALL properties as simple get/set and some extra code for lazy loaded properties.
So in your case - the problem is that your rules is attached to a property that is NOT the one set by the user. The user actually sets the PrimaryContact property - and I would rather have a rule that then sets the PrimaryContactId and runs the other rules.
So I believe all rules that need to run should have PrimaryContact as the PrimaryProperty.
Also remember that a rule may set an error or warning on another property than the PrimaryProperty.
Copyright (c) Marimer LLC