PostSharp 4.3 / / Post­Sharp Documentation / Standard Patterns / INotify­Property­Changed / Handling Corner Cases of the Notify­Property­Changed Aspect
Handling Corner Cases of the NotifyPropertyChanged Aspect

Postsharp includes a number of attributes for customizing the Model Pattern’s behaviour and for handling special dependencies.

This topic contains the following sections:

Ignoring Changes to Properties

Use the IgnoreAutoChangeNotificationAttribute class attribute to prevent an OnPropertyChanged event from being invoked when setting a property. For example, the CustomerModel class contains a Country property amongst others:

C#
[NotifyPropertyChanged]
                        

                        public
                         
                        class
                         CustomerModel 
{ 
    
                        public
                         
                        string
                         FirstName { 
                        get
                        ; 
                        set
                        ; } 
    
                        public
                         
                        string
                         LastName { 
                        get
                        ; 
                        set
                        ; } 

    
                        public
                         
                        string
                         Phone { 
                        get
                        ; 
                        set
                        ; } 
    
                        public
                         
                        string
                         Mobile { 
                        get
                        ; 
                        set
                        ; } 
    
                        public
                         
                        string
                         Email { 
                        get
                        ; 
                        set
                        ; } 
    
                        public
                         
                        string
                         Country { 
                        get
                        ; 
                        set
                        ;}
}
                      

To prevent a property notification from being invoked when the Country’s value is set, simply place the IgnoreAutoChangeNotificationAttribute attribute above the property:

C#
[NotifyPropertyChanged]
                        

                        public
                         
                        class
                         CustomerModel 
{ 
    
                        public
                         
                        string
                         FirstName { 
                        get
                        ; 
                        set
                        ; } 
    
                        public
                         
                        string
                         LastName { 
                        get
                        ; 
                        set
                        ; } 
    
                        public
                         
                        string
                         Phone { 
                        get
                        ; 
                        set
                        ; } 
    
                        public
                         
                        string
                         Mobile { 
                        get
                        ; 
                        set
                        ; } 
    
                        public
                         
                        string
                         Email { 
                        get
                        ; 
                        set
                        ; } 

    [IgnoreAutoChangeNotification]
    
                        public
                         
                        string
                         Country { 
                        get
                        ; 
                        set
                        ;}
}
                      
Handling Virtual Calls, References, and Delegates in a Get Accessor

If a get accessor calls a virtual method from its class or a delegate, or references a property of another object (without using canonical form this.field.Property), PostSharp will generate an error because it cannot resolve such a dependency at build time. To suppress this error, you can add the [SafeForDependencyAnalysisAttribute] custom attribute to the property accessor (or in any method used by the property accessor). This custom attribute instructs PostSharp that the property accessor is “safe” – in other words, it contains only dependencies in the canonical form this.field.Property.

For example, say CustomerModel contains a virtual method called ValidateCountry() which is used by the get accessor of its Country property:

C#
[NotifyPropertyChanged]
                        

                        public
                         
                        class
                         CustomerModel 
{ 
  
                        // Details skipped.
                        

                        

                        protected
                         
                        virtual
                         
                        bool
                         ValidateCountry(
                        string
                         s)
{
  
                        if
                         (s!=
                        null
                        )
    
                        return
                         
                        true
                        ;
  
                        else
                        
    
                        return
                         
                        false
                        ;
}

  
                        public
                         
                        string
                         Country 
  { 
    
                        get
                        
    {
      
                        if
                        (
                        this
                        .ValidateCountry(
                        value
                        ))
        
                        return
                         
                        value
                        ;
      
                        else
                        
       
                        return
                         
                        null
                        ;
    }
    
                        set
                        ;
  }
}
                      

In this situation the property relies on a virtual method which PostSharp cannot resolve at build time, so the SafeForDependencyAnalysisAttribute attribute can be placed on the Country property suppress this error:

C#
[NotifyPropertyChanged]
                        

                        public
                         
                        class
                         CustomerModel 
{ 
   
                        // Details skipped.
                        

                        
  
                        public
                         
                        virtual
                         
                        bool
                         Test(
                        string
                         s)
  {
    
                        if
                         (s!=
                        null
                        )
      
                        return
                         
                        true
                        ;
    
                        else
                        
      
                        return
                         
                        false
                        ;
  }

  [SafeForDependencyAnalysisAttribute]
  
                        public
                         
                        string
                         Country 
  { 
    
                        get
                        
    {
      
                        if
                        (
                        this
                        .test(
                        value
                        ) == 
                        true
                        )
        
                        return
                         
                        value
                        ;
      
                        else
                        
       
                        return
                         
                        null
                        ;
    }
    
                        set
                        ;
  }
}
                      
Note Note

By using SafeForDependencyAnalysisAttribute, you are taking the responsibility that your code only has dependencies that are given either in the canonical form of this.field.Property either explicitly using the On() construct (see the next section). If you are using this custom attribute but have non-canonical dependencies, some property changes may not be detected in which case no notification will be generated.

Handling Local Variables

Properties may depend on a property of another object, and sometimes this object must be stored in a local variable. Most of the times, PostSharp is able to analyze chains of dependencies in properties that are dependent on a property of a local variable. However, when the variable is assigned in a loop or in an exception handler, the analysis cannot be executed.

If PostSharp does not understand your code, you need to use the SafeForDependencyAnalysisAttribute attribute and the Depends.On() method as described above.

Handling Dependencies on Pure Methods

Often times an object will depend on a method which is solely dependent on its input parameters to produce an output (e.g. a static method). Consider the following variation to CustomerModel where the ValidPhoneNumber property logic has been moved into a static method called GetValidPhoneNumber() which exists in a separate helper class called ContactHelper:

C#
public
                         
                        class
                         ContactHelper
{
  [Pure]
  
                        public
                         
                        static
                         
                        string
                         GetValidPhoneNumber(
                        string
                         firstPhoneNumber, 
                        string
                         secondPhoneNumber)
  {
    
                        if
                        (firstPhoneNumber != 
                        null
                        )
      
                        return
                         firstPhoneNumber;
    
                        else
                         
                        if
                         (secondPhoneNumber != 
                        null
                        )
      
                        return
                         secondPhoneNumber;
    
                        else
                        
      
                        return
                         
                        null
                        ;    
  }
}

[NotifyPropertyChanged]
                        

                        public
                         
                        class
                         CustomerModel 
{ 
  
                        public
                         Contact PrimaryContact{
                        get
                        ; 
                        set
                        ;}
  
                        public
                         Contact SecondaryContact{
                        get
                        ; 
                        set
                        ;}

  
                        public
                         
                        string
                         ValidPhoneNumber
  { 
    
                        get
                         {
      
                        return
                         ContactHelper.GetValidPhoneNumber(
                        this
                        .PrimaryContact.Phone, 
                        this
                        .SecondaryContact.Phone);
    }
  }
}
                      

Since GetValidPhoneNumber() is a standalone method of another class, it is not analyzed. Therefore the PureAttribute attribute needs to be applied to this method to acknowledge this dependency.

See Also