Let's begin by defining the attribute which will allow some properties to be skipped by the aspect:

[AttributeUsage(AttributeTargets.Property)]
public class DontNotifyAttribute : Attribute
{
        
}

Pretty simple, isn't it? :)

And now, the aspect.

If you look at the original aspect, you will notice, above the OnPropertySet method the following custom attributes:

[OnLocationSetValueAdvice, MulticastPointcut(Targets = MulticastTargets.Property, Attributes = MulticastAttributes.Instance | MulticastAttributes.NonAbstract)]

What is interesting here if the MulticastPointcut attribute. It defines on which targets the aspect will be applied. In the documentation, it is said that you can use a MethodPointcut which allow you to define a function which will return the targets you want. We then just have to create this function, and replace the MulticastPointcut attribute by MethodPointcut:

private IEnumerable<PropertyInfo> SelectProperties(Type type)
{
    const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public;

    return from property in type.GetProperties(bindingFlags)
            where property.CanWrite && !property.IsDefined(typeof(DontNotifyAttribute), true)
            select property;
}
        
[OnLocationSetValueAdvice, MethodPointcut("SelectProperties")]
public void OnPropertySet(LocationInterceptionArgs args)
{
    if (args.Value == args.GetCurrentValue())
        return;

    args.ProceedSetValue();

    OnPropertyChangedMethod.Invoke(args.Location.Name);
}

The SelectProperties function will simply return all the properties of the class, without those marked with DontNotifyAttribute.

As simply as that, thanks to the PostSharp framework.

See you soon!