Firing business rules on property changed for a private backing field

Firing business rules on property changed for a private backing field

Old forum URL: forums.lhotka.net/forums/t/12773.aspx


EGraeb posted on Tuesday, October 14, 2014

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?

 

JonnyBee replied on Wednesday, October 15, 2014

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