We are just upgrading from an older version of CSLA to the new framework (4.5.6) and having a little difficulty with one scenario.
I have a CSLA class (Model) referencing properties on another CSLA class (Relation) as a private backing field. The registration is setup like this:
Public Shared ReadOnly ReferenceProperty As PropertyInfo(Of ReferenceType) = RegisterProperty(Of ReferenceType)(Function(c) c.ReferenceType, "Reference Type", RelationshipTypes.PrivateField)
Public Property ReferenceType() As ReferenceType
Get
Return GetProperty(ReferenceProperty,_reference.ReferenceType)
End Get
Set(ByVal value As ReferenceType)
SetProperty(ReferenceProperty,_reference.ReferenceType,value)
End Set
End Property
The "Model" montors for changes to the property in "Relation" and fires OnPropertyChanged("string name of property") on itself to fire the business rules on itself in case it's changed elsewhere. The property in Relation and the property in Model have the same string name:
Private Sub ReferencePropertyChanged(ByVal sender As Object, ByVal e As PropertyChangedEventArgs) Handles _reference.PropertyChanged
If Me.GetType.GetMembers.Select(Function(m) m.Name).Contains(e.PropertyName) Then
OnPropertyChanged(e.PropertyName)
End If
End Sub
The problem is that firing this OnPropertyChanged doesn't fire the business rules tied to the Model property any more. I can fire the business rule manually by adding a little more reflection and that works fine:
Dim prop As IPropertyInfo = FindProperty(e.PropertyName)
If prop IsNot Nothing Then
BusinessRules.CheckRules(prop)
End If
Whenever I need to use reflection though I run under the assumption I must be doing something wrong. Is there something extra I need to do to have validation rules fire OnPropertyChanged for private backing fields?
Hi,
OnPropertyChanged on a BO must NEVER be used to trigger business rules!!!
It must ONLY be used to notify the UI of changes to content or state of a property.
There are 3 ways to trigger a business rules for a property:
The difference between PropertyHasChanged and CheckPropertyRules is that PropertyHasChanged will also mark the object as Dirty before calling CheckPropertyRules that in turn will call BusinessRules.CheckRules and call OnPropertyChanged as necessary.
So you could write the event handler as:
private void ReferencePropertyChanged(object sender, PropertyChangedEventArgs e) { // you could even check that the propertyInfo is flagged as PrivateField - not shown
var myProperty = FieldManager.GetRegisteredProperties().FirstOrDefault(p => p.Name == e.PropertyName); if (myProperty != null) { PropertyHasChanged(myProperty); // or if you do not want to mark the object as dirty // CheckPropertyRules(myProperty); } }
and just for reference this is the PropertyHasChanged and CheckPropertyRules method:
protected virtual void PropertyHasChanged(Csla.Core.IPropertyInfo property) { MarkDirty(true); CheckPropertyRules(property); }
protected virtual void CheckPropertyRules(IPropertyInfo property) { var propertyNames = BusinessRules.CheckRules(property); if (ApplicationContext.PropertyChangedMode == ApplicationContext.PropertyChangedModes.Windows) OnPropertyChanged(property); else foreach (var name in propertyNames) OnPropertyChanged(name); }
Copyright (c) Marimer LLC