コード例 #1
0
        /// <summary>
        /// Sets the value of a specific property.
        /// </summary>
        /// <param name="property">The property to set.</param>
        /// <param name="value">Value of the property.</param>
        /// <param name="notifyOnChange">If <c>true</c>, the <see cref="INotifyPropertyChanged.PropertyChanged"/> event will be invoked.</param>
        /// <exception cref="PropertyNotNullableException">The property is not nullable, but <paramref name="value"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">The <paramref name="property"/> is <c>null</c>.</exception>
        protected internal void SetValue <TValue>(PropertyData property, TValue value, bool notifyOnChange = true)
        {
            Argument.IsNotNull("property", property);

            // Is the object currently read-only (and aren't we changing that)?
            if (IsReadOnly || _isFrozen)
            {
                if (property != IsReadOnlyProperty)
                {
                    Log.Warning("Cannot set property '{0}', object is currently read-only", property.Name);
                    return;
                }
            }

            if (property.IsCalculatedProperty)
            {
                Log.Warning("Cannot set property '{0}', the property is a calculated property", property.Name);
                return;
            }

            if ((value != null) && !property.Type.IsInstanceOfTypeEx(value))
            {
                if (!value.GetType().IsCOMObjectEx())
                {
                    throw Log.ErrorAndCreateException(msg => new InvalidPropertyValueException(property.Name, property.Type, value.GetType()),
                                                      "Cannot set value '{0}' to property '{1}' of type '{2}', the value is invalid", value, property.Name, GetType().FullName);
                }
            }

            var    notify = false;
            TValue oldValue;

            lock (_lock)
            {
                var changeNotificationsSuspensionContext = _changeNotificationsSuspensionContext;

                oldValue = GetValueFromPropertyBag <TValue>(property.Name);
                var areOldAndNewValuesEqual = ObjectHelper.AreEqualReferences(oldValue, value);

                if (!areOldAndNewValuesEqual)
                {
                    SetValueToPropertyBag(property.Name, value);
                }

                notify = (notifyOnChange && (AlwaysInvokeNotifyChanged || !areOldAndNewValuesEqual));

                if (changeNotificationsSuspensionContext != null)
                {
                    changeNotificationsSuspensionContext.Add(property.Name);
                    notify = false;
                }
            }

            // Notify outside lock
            if (notify)
            {
                RaisePropertyChanged(property.Name, BoxingCache.GetBoxedValue(oldValue), BoxingCache.GetBoxedValue(value));
            }
        }