private object TryProvideValueImpl(IServiceProvider serviceProvider, bool allowDeferredReference, bool mustReturnDeferredResourceReference) { // Get prefetchedValue DeferredResourceReference prefetchedValue = PrefetchedValue; object value; if (prefetchedValue == null) { // Do a normal look up. value = FindResourceInEnviroment(serviceProvider, allowDeferredReference, mustReturnDeferredResourceReference); } else { // If we have a Deferred Value, first check the current parse stack for a better (nearer) // value. This happens when this is a parse of deferred content and there is another // Resource Dictionary availible above this, yet still part of this deferred content. // This searches up to the outer most enclosing resource dictionary. value = FindResourceInDeferredContent(serviceProvider, allowDeferredReference, mustReturnDeferredResourceReference); // If we didn't find a new value in this part of deferred content // then use the existing prefetchedValue (DeferredResourceReference) if (value == DependencyProperty.UnsetValue) { value = allowDeferredReference ? prefetchedValue : prefetchedValue.GetValue(BaseValueSourceInternal.Unknown); } } return(value); }
/// <summary> /// This method is called when the cached value of the resource has /// been invalidated. E.g. after a new Resources property is set somewhere /// in the ancestory. /// </summary> private void InvalidateCacheValue() { object resource = _cachedResourceValue; // If the old value was a DeferredResourceReference, it should be // removed from its Dictionary's list to avoid a leak (bug 1624666). DeferredResourceReference deferredResourceReference = _cachedResourceValue as DeferredResourceReference; if (deferredResourceReference != null) { if (deferredResourceReference.IsInflated) { // use the inflated value for the Freezable test below resource = deferredResourceReference.Value; } else { // stop listening for the Inflated event if (ReadInternalState(InternalState.IsListeningForInflated)) { deferredResourceReference.RemoveInflatedListener(this); WriteInternalState(InternalState.IsListeningForInflated, false); } } deferredResourceReference.RemoveFromDictionary(); } StopListeningForFreezableChanges(resource); _cachedResourceValue = null; WriteInternalState(InternalState.HasCachedResourceValue, false); }
// Token: 0x06000875 RID: 2165 RVA: 0x0001B8AC File Offset: 0x00019AAC internal object GetRawValue(DependencyObject d, out object source, DependencyProperty dp) { if (!this.ReadInternalState(ResourceReferenceExpression.InternalState.IsMentorCacheValid)) { this._mentorCache = Helper.FindMentor(d); this.WriteInternalState(ResourceReferenceExpression.InternalState.IsMentorCacheValid, true); if (this._mentorCache != null && this._mentorCache != this._targetObject) { FrameworkElement frameworkElement; FrameworkContentElement frameworkContentElement; Helper.DowncastToFEorFCE(this._mentorCache, out frameworkElement, out frameworkContentElement, true); if (frameworkElement != null) { frameworkElement.ResourcesChanged += this.InvalidateExpressionValue; } else { frameworkContentElement.ResourcesChanged += this.InvalidateExpressionValue; } } } object obj; if (this._mentorCache != null) { FrameworkElement fe; FrameworkContentElement fce; Helper.DowncastToFEorFCE(this._mentorCache, out fe, out fce, true); obj = FrameworkElement.FindResourceInternal(fe, fce, dp, this._resourceKey, null, true, false, null, false, out source); } else { obj = FrameworkElement.FindResourceFromAppOrSystem(this._resourceKey, out source, false, true, false); } if (obj == null) { obj = DependencyProperty.UnsetValue; } this._cachedResourceValue = obj; this.WriteInternalState(ResourceReferenceExpression.InternalState.HasCachedResourceValue, true); object resource = obj; DeferredResourceReference deferredResourceReference = obj as DeferredResourceReference; if (deferredResourceReference != null) { if (deferredResourceReference.IsInflated) { resource = (deferredResourceReference.Value as Freezable); } else if (!this.ReadInternalState(ResourceReferenceExpression.InternalState.IsListeningForInflated)) { deferredResourceReference.AddInflatedListener(this); this.WriteInternalState(ResourceReferenceExpression.InternalState.IsListeningForInflated, true); } } this.ListenForFreezableChanges(resource); return(obj); }
// Token: 0x06000881 RID: 2177 RVA: 0x0001BC70 File Offset: 0x00019E70 internal void OnDeferredResourceInflated(DeferredResourceReference deferredResourceReference) { if (this.ReadInternalState(ResourceReferenceExpression.InternalState.IsListeningForInflated)) { deferredResourceReference.RemoveInflatedListener(this); this.WriteInternalState(ResourceReferenceExpression.InternalState.IsListeningForInflated, false); } this.ListenForFreezableChanges(deferredResourceReference.Value); }
private object TryProvideValueWithDiagnosticEvent(IServiceProvider serviceProvider, bool allowDeferredReference, bool mustReturnDeferredResourceReference) { IProvideValueTarget provideValueTarget = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; if (provideValueTarget == null || provideValueTarget.TargetObject == null || provideValueTarget.TargetProperty == null || ResourceDictionaryDiagnostics.ShouldIgnoreProperty(provideValueTarget.TargetProperty)) { // if there's no target, or target is ignorable, get the value the quick way. return(TryProvideValueImpl(serviceProvider, allowDeferredReference, mustReturnDeferredResourceReference)); } ResourceDictionaryDiagnostics.LookupResult result; object value; bool success = false; try { // request a result of the lookup result = ResourceDictionaryDiagnostics.RequestLookupResult(this); // do the lookup - the ResourceDictionary that resolves the reference will fill in the result value = TryProvideValueImpl(serviceProvider, allowDeferredReference, mustReturnDeferredResourceReference); // for the purposes of diagnostics, a deferred reference is a success - // we only need the dictionary that holds the value, not the value itself DeferredResourceReference deferredReference = value as DeferredResourceReference; if (deferredReference != null) { success = true; ResourceDictionary dict = deferredReference.Dictionary; if (dict != null) { // the result may not have been recorded yet ResourceDictionaryDiagnostics.RecordLookupResult(ResourceKey, dict); } } else { success = (value != DependencyProperty.UnsetValue); } } finally { // revert the request ResourceDictionaryDiagnostics.RevertRequest(this, success); } // raise the diagnostic event if (success) { ResourceDictionaryDiagnostics.OnStaticResourceResolved(provideValueTarget.TargetObject, provideValueTarget.TargetProperty, result); } return(value); }
// when a deferred resource reference is inflated, the value may need extra // work internal void OnDeferredResourceInflated(DeferredResourceReference deferredResourceReference) { if (ReadInternalState(InternalState.IsListeningForInflated)) { // once the value is inflated, stop listening for the event deferredResourceReference.RemoveInflatedListener(this); WriteInternalState(InternalState.IsListeningForInflated, false); } ListenForFreezableChanges(deferredResourceReference.Value); }
// Token: 0x06000864 RID: 2148 RVA: 0x0001B4A4 File Offset: 0x000196A4 private object TryProvideValueImpl(IServiceProvider serviceProvider, bool allowDeferredReference, bool mustReturnDeferredResourceReference) { DeferredResourceReference prefetchedValue = this.PrefetchedValue; object obj; if (prefetchedValue == null) { obj = this.FindResourceInEnviroment(serviceProvider, allowDeferredReference, mustReturnDeferredResourceReference); } else { obj = this.FindResourceInDeferredContent(serviceProvider, allowDeferredReference, mustReturnDeferredResourceReference); if (obj == DependencyProperty.UnsetValue) { obj = (allowDeferredReference ? prefetchedValue : prefetchedValue.GetValue(BaseValueSourceInternal.Unknown)); } } return(obj); }
// Token: 0x06000863 RID: 2147 RVA: 0x0001B3DC File Offset: 0x000195DC private object TryProvideValueWithDiagnosticEvent(IServiceProvider serviceProvider, bool allowDeferredReference, bool mustReturnDeferredResourceReference) { IProvideValueTarget provideValueTarget = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; if (provideValueTarget == null || provideValueTarget.TargetObject == null || provideValueTarget.TargetProperty == null || ResourceDictionaryDiagnostics.ShouldIgnoreProperty(provideValueTarget.TargetProperty)) { return(this.TryProvideValueImpl(serviceProvider, allowDeferredReference, mustReturnDeferredResourceReference)); } bool flag = false; ResourceDictionaryDiagnostics.LookupResult result; object obj; try { result = ResourceDictionaryDiagnostics.RequestLookupResult(this); obj = this.TryProvideValueImpl(serviceProvider, allowDeferredReference, mustReturnDeferredResourceReference); DeferredResourceReference deferredResourceReference = obj as DeferredResourceReference; if (deferredResourceReference != null) { flag = true; ResourceDictionary dictionary = deferredResourceReference.Dictionary; if (dictionary != null) { ResourceDictionaryDiagnostics.RecordLookupResult(this.ResourceKey, dictionary); } } else { flag = (obj != DependencyProperty.UnsetValue); } } finally { ResourceDictionaryDiagnostics.RevertRequest(this, flag); } if (flag) { ResourceDictionaryDiagnostics.OnStaticResourceResolved(provideValueTarget.TargetObject, provideValueTarget.TargetProperty, result); } return(obj); }
// Token: 0x0600087A RID: 2170 RVA: 0x0001BA78 File Offset: 0x00019C78 private void InvalidateCacheValue() { object resource = this._cachedResourceValue; DeferredResourceReference deferredResourceReference = this._cachedResourceValue as DeferredResourceReference; if (deferredResourceReference != null) { if (deferredResourceReference.IsInflated) { resource = deferredResourceReference.Value; } else if (this.ReadInternalState(ResourceReferenceExpression.InternalState.IsListeningForInflated)) { deferredResourceReference.RemoveInflatedListener(this); this.WriteInternalState(ResourceReferenceExpression.InternalState.IsListeningForInflated, false); } deferredResourceReference.RemoveFromDictionary(); } this.StopListeningForFreezableChanges(resource); this._cachedResourceValue = null; this.WriteInternalState(ResourceReferenceExpression.InternalState.HasCachedResourceValue, false); }
/// <summary> /// Called to evaluate the ResourceReferenceExpression value /// </summary> /// <param name="d">DependencyObject being queried</param> /// <param name="source">Source object that the resource is found on</param> /// <param name="dp">DependencyProperty</param> /// <returns>Computed value. Unset if unavailable.</returns> /// <remarks> /// This routine has been separated from the above GetValue call because it is /// invoked by the ResourceReferenceExpressionConverter during serialization. /// </remarks> internal object GetRawValue(DependencyObject d, out object source, DependencyProperty dp) { // Find the mentor node to invoke FindResource on. For example // <Button> // <Button.Background> // <SolidColorBrush Color="{DynamicResource MyColor}" /> // </Button.Background> // </Button // Button is the mentor for the ResourceReference on SolidColorBrush if (ReadInternalState(InternalState.IsMentorCacheValid) == false) { // Find the mentor by walking up the InheritanceContext // links and update the cache _mentorCache = Helper.FindMentor(d); WriteInternalState(InternalState.IsMentorCacheValid, true); // If the mentor is different from the targetObject as will be the case // in the example described above, make sure you listen for ResourcesChanged // event on the mentor. That way you will be notified of ResourceDictionary // changes as well as logical tree changes if (_mentorCache != null && _mentorCache != _targetObject) { Debug.Assert(_targetObject == d, "TargetObject that this expression is attached to must be the same as the one on which its value is being queried"); FrameworkElement mentorFE; FrameworkContentElement mentorFCE; Helper.DowncastToFEorFCE(_mentorCache, out mentorFE, out mentorFCE, true); if (mentorFE != null) { mentorFE.ResourcesChanged += new EventHandler(InvalidateExpressionValue); } else { mentorFCE.ResourcesChanged += new EventHandler(InvalidateExpressionValue); } } } object resource; if (_mentorCache != null) { FrameworkElement fe; FrameworkContentElement fce; Helper.DowncastToFEorFCE(_mentorCache, out fe, out fce, true /*throwIfNeither*/); // If there is a mentor do a FindResource call starting at that node resource = FrameworkElement.FindResourceInternal(fe, fce, dp, _resourceKey, null, // unlinkedParent true, // allowDeferredResourceReference false, // mustReturnDeferredResourceReference null, // boundaryElement false, // disableThrowOnResourceFailure out source); } else { // If there is no mentor then simply search the App and the Themes for the right resource resource = FrameworkElement.FindResourceFromAppOrSystem(_resourceKey, out source, false, // disableThrowOnResourceFailure true, // allowDeferredResourceReference false /* mustReturnDeferredResourceReference*/); } if (resource == null) { // Assuming that null means the value doesn't exist in the resources section resource = DependencyProperty.UnsetValue; } // Update the cached values with this resource instance _cachedResourceValue = resource; WriteInternalState(InternalState.HasCachedResourceValue, true); object effectiveResource = resource; DeferredResourceReference deferredResourceReference = resource as DeferredResourceReference; if (deferredResourceReference != null) { if (deferredResourceReference.IsInflated) { // use the inflated value in the Freezable test below effectiveResource = deferredResourceReference.Value as Freezable; } else { // listen for inflation, so we can do the Freezable test then if (!ReadInternalState(InternalState.IsListeningForInflated)) { deferredResourceReference.AddInflatedListener(this); WriteInternalState(InternalState.IsListeningForInflated, true); } } } ListenForFreezableChanges(effectiveResource); // Return the resource return(resource); }
/// <summary> /// Fetches the resource corresponding to the given key from this dictionary. /// Returns a DeferredResourceReference if the object has not been inflated yet. /// </summary> internal object FetchResource( object resourceKey, bool allowDeferredResourceReference, bool mustReturnDeferredResourceReference, out bool canCache) { Debug.Assert(resourceKey != null, "ResourceKey cannot be null"); if (allowDeferredResourceReference) { if (ContainsBamlObjectFactory(resourceKey) || (mustReturnDeferredResourceReference && Contains(resourceKey))) { canCache = false; DeferredResourceReference deferredResourceReference; if (!IsThemeDictionary) { if (_ownerApps != null) { deferredResourceReference = new DeferredAppResourceReference(this, resourceKey); } else { deferredResourceReference = new DeferredResourceReference(this, resourceKey); } // Cache the deferredResourceReference so that it can be validated // in case of a dictionary change prior to its inflation if (_deferredResourceReferences == null) { _deferredResourceReferences = new WeakReferenceList(); } _deferredResourceReferences.Add( deferredResourceReference, true /*SkipFind*/); } else { deferredResourceReference = new DeferredThemeResourceReference(this, resourceKey); } return deferredResourceReference; } } return GetValue(resourceKey, out canCache); }
internal StaticResourceHolder(object resourceKey, DeferredResourceReference prefetchedValue) : base(resourceKey) { _prefetchedValue = prefetchedValue; }