/// <summary> /// We calling it, you are forcing a property being tracked. /// </summary> /// <param name="propertyName"></param> public void SingleTypePropertyNotifierPropertyChanged(string propertyName) { VariableInfoDescriptor.Flags |= BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.GetField; var propertyMember = SingleTypedPropertiesOwnerType.GetVariableMember(propertyName, VariableInfoDescriptor); // There is no member that can be handled, so we return. if (propertyMember == null) { return; } var propertyType = propertyMember.GetVariableType(); PropertyType typedPropertyValue; var propertyValue = propertyMember.GetValue(SingleTypedPropertiesOwner); // We want to assign property value (object) to typed property value. if (propertyComparisonMode == PropertyComparisonMode.ValueType && TrackingPropertyType == propertyType || propertyComparisonMode == PropertyComparisonMode.ReferenceType && TrackingPropertyType.IsAssignableFrom(propertyType)) { typedPropertyValue = (PropertyType)propertyValue; } else { return; // The type of the property does not meet the requirements, so we skip the property } var isPropertNameTracked = cachedPropertyValues.ContainsKey(propertyName); // We want to abort if tracking property name is untracked and tracking property value is equals default/null. if (!isPropertNameTracked && CanHandleDefaultValue && PropertyValueEqualityComparer.Equals(typedPropertyValue !, TrackingPropertyDefaultValue !)) { return; } void trackPropertyViaArgs(PropertyCachedEventArgs <PropertyType> args) { cachedPropertyValues.Add(propertyName, args.PropertyValue !); OnPropertyCacheAdded(args); } void trackProperty(PropertyType uncachedProperty) { var args = new PropertyCachedEventArgs <PropertyType>(propertyName, uncachedProperty); trackPropertyViaArgs(args); } void untrackProperty(PropertyType cachedProperty, bool isRetrack) { cachedPropertyValues.Remove(propertyName); if (isRetrack && CanSkipPropertyRemovedEventInvocationWhenRetracking) { return; } var args = new PropertyCacheRemovedEventArgs <PropertyType>(propertyName, cachedProperty); OnPropertyCacheRemoved(args); } void retrackProperty(PropertyType cachedProperty, PropertyType uncachedProperty) { untrackProperty(cachedProperty, true); var args = new PropertyCachedEventArgs <PropertyType>(propertyName, uncachedProperty, cachedProperty); trackPropertyViaArgs(args); } if (!isPropertNameTracked) { var args = new PropertyCachingEventArgs <PropertyType>(propertyName, typedPropertyValue); OnPropertyCacheAdding(args); if (!args.CanTrackProperty) { return; } // Add new subscription trackProperty(typedPropertyValue !); } else { var cachedProperty = cachedPropertyValues[propertyName]; if (CanHandleDefaultValue && PropertyValueEqualityComparer.Equals(typedPropertyValue !, TrackingPropertyDefaultValue !)) { untrackProperty(cachedProperty, false); }
protected void OnPropertyCacheAdded(PropertyCachedEventArgs <PropertyType> args) => PropertyAdded?.Invoke(this, args);