[FriendAccessAllowed] // Built into Base, also used by Framework. internal object GetDefaultValue(DependencyObject owner, DependencyProperty property) { Debug.Assert(owner != null && property != null, "Caller must provide owner and property or this method will throw in the event of a cache miss."); // If we are not using a DefaultValueFactory (common case) // just return _defaultValue DefaultValueFactory defaultFactory = _defaultValue as DefaultValueFactory; if (defaultFactory == null) { return _defaultValue; } // If the owner is Sealed it must not have a cached Freezable default value, // regardless of whether or not the owner is a Freezable. The reason // for this is that a default created using the FreezableDefaultValueFactory // will attempt to set itself as a local value if it is changed. Since the owner // is Sealed this will throw an exception. // // The solution to this if the owner is a Freezable is to toss out all cached // default values when we Seal. If the owner is not a Freezable we'll promote // the value to locally cached. Either way no Sealed DO can have a cached // default value, so we'll return the frozen default value instead. if (owner.IsSealed) { return defaultFactory.DefaultValue; } // See if we already have a valid default value that was // created by a prior call to GetDefaultValue. object result = GetCachedDefaultValue(owner, property); if (result != DependencyProperty.UnsetValue) { // When sealing a DO we toss out all the cached values (see DependencyObject.Seal()). // We technically only need to throw out cached values created via the // FreezableDefaultValueFactory, but it's more consistent this way. Debug.Assert(!owner.IsSealed, "If the owner is Sealed we should not have a cached default value"); return result; } // Otherwise we need to invoke the factory to create the DefaultValue // for this property. result = defaultFactory.CreateDefaultValue(owner, property); // Default value validation ensures that default values do not have // thread affinity. This is because a default value is typically // stored in the shared property metadata and handed out to all // instances of the owning DependencyObject type. // // DefaultValueFactory.CreateDefaultValue ensures that the default // value has thread-affinity to the current thread. We can thus // skip that portion of the default value validation by calling // ValidateFactoryDefaultValue. Debug.Assert(!(result is DispatcherObject) || ((DispatcherObject)result).Dispatcher == owner.Dispatcher); property.ValidateFactoryDefaultValue(result); // Cache the created DefaultValue so that we can consistently hand // out the same default each time we are asked. SetCachedDefaultValue(owner, property, result); return result; }
[FriendAccessAllowed] // Built into Base, also used by Framework. internal object GetDefaultValue(DependencyObject owner, DependencyProperty property) { Debug.Assert(owner != null && property != null, "Caller must provide owner and property or this method will throw in the event of a cache miss."); // If we are not using a DefaultValueFactory (common case) // just return _defaultValue DefaultValueFactory defaultFactory = _defaultValue as DefaultValueFactory; if (defaultFactory == null) { return(_defaultValue); } // If the owner is Sealed it must not have a cached Freezable default value, // regardless of whether or not the owner is a Freezable. The reason // for this is that a default created using the FreezableDefaultValueFactory // will attempt to set itself as a local value if it is changed. Since the owner // is Sealed this will throw an exception. // // The solution to this if the owner is a Freezable is to toss out all cached // default values when we Seal. If the owner is not a Freezable we'll promote // the value to locally cached. Either way no Sealed DO can have a cached // default value, so we'll return the frozen default value instead. if (owner.IsSealed) { return(defaultFactory.DefaultValue); } // See if we already have a valid default value that was // created by a prior call to GetDefaultValue. object result = GetCachedDefaultValue(owner, property); if (result != DependencyProperty.UnsetValue) { // When sealing a DO we toss out all the cached values (see DependencyObject.Seal()). // We technically only need to throw out cached values created via the // FreezableDefaultValueFactory, but it's more consistent this way. Debug.Assert(!owner.IsSealed, "If the owner is Sealed we should not have a cached default value"); return(result); } // Otherwise we need to invoke the factory to create the DefaultValue // for this property. result = defaultFactory.CreateDefaultValue(owner, property); // Default value validation ensures that default values do not have // thread affinity. This is because a default value is typically // stored in the shared property metadata and handed out to all // instances of the owning DependencyObject type. // // DefaultValueFactory.CreateDefaultValue ensures that the default // value has thread-affinity to the current thread. We can thus // skip that portion of the default value validation by calling // ValidateFactoryDefaultValue. Debug.Assert(!(result is DispatcherObject) || ((DispatcherObject)result).Dispatcher == owner.Dispatcher); property.ValidateFactoryDefaultValue(result); // Cache the created DefaultValue so that we can consistently hand // out the same default each time we are asked. SetCachedDefaultValue(owner, property, result); return(result); }