@@ -695,6 +695,8 @@ private void ClearWithoutLock()
695
695
// to the old resource before we clear it.
696
696
ValidateDeferredResourceReferences ( null ) ;
697
697
698
+ _weakDeferredResourceReferencesMap ? . Clear ( ) ;
699
+
698
700
// remove inheritance context from all values that got it from
699
701
// this dictionary
700
702
RemoveInheritanceContextFromValues ( ) ;
@@ -706,6 +708,61 @@ private void ClearWithoutLock()
706
708
}
707
709
}
708
710
711
+ // optimized contains method used in FetchResource
712
+ private void Contains ( object key , bool mustReturnDeferredResourceReference , out bool contains , out bool containsBamlObjectFactory )
713
+ {
714
+ contains = false ;
715
+ containsBamlObjectFactory = false ;
716
+
717
+ bool result = _baseDictionary . Contains ( key ) ;
718
+
719
+ if ( result )
720
+ {
721
+ KeyRecord keyRecord = _baseDictionary [ key ] as KeyRecord ;
722
+ if ( keyRecord != null && _deferredLocationList . Contains ( keyRecord ) )
723
+ {
724
+ contains = false ;
725
+ }
726
+ else
727
+ {
728
+ contains = true ;
729
+ }
730
+
731
+ if ( mustReturnDeferredResourceReference
732
+ && contains )
733
+ {
734
+ return ;
735
+ }
736
+
737
+ containsBamlObjectFactory = keyRecord is not null ;
738
+
739
+ if ( containsBamlObjectFactory )
740
+ {
741
+ return ;
742
+ }
743
+ }
744
+
745
+ //Search for the value in the Merged Dictionaries
746
+ if ( _mergedDictionaries != null )
747
+ {
748
+ for ( int i = MergedDictionaries . Count - 1 ; i > - 1 ; i -- )
749
+ {
750
+ // Note that MergedDictionaries collection can also contain null values
751
+ ResourceDictionary mergedDictionary = MergedDictionaries [ i ] ;
752
+ if ( mergedDictionary != null )
753
+ {
754
+ mergedDictionary . Contains ( key , mustReturnDeferredResourceReference , out contains , out containsBamlObjectFactory ) ;
755
+
756
+ if ( containsBamlObjectFactory
757
+ || ( mustReturnDeferredResourceReference && contains ) )
758
+ {
759
+ return ;
760
+ }
761
+ }
762
+ }
763
+ }
764
+ }
765
+
709
766
/// <summary>
710
767
/// Determines whether the IDictionary contains an element with the specified key.
711
768
/// if the Key is not contained in this ResourceDictionary, it will check in the MergedDictionaries too
@@ -1718,8 +1775,10 @@ private object FetchResource(
1718
1775
1719
1776
if ( allowDeferredResourceReference )
1720
1777
{
1721
- if ( ContainsBamlObjectFactory ( resourceKey ) ||
1722
- ( mustReturnDeferredResourceReference && Contains ( resourceKey ) ) )
1778
+ Contains ( resourceKey , mustReturnDeferredResourceReference , out bool contains , out bool containsBamlObjectFactory ) ;
1779
+
1780
+ if ( containsBamlObjectFactory
1781
+ || ( mustReturnDeferredResourceReference && contains ) )
1723
1782
{
1724
1783
canCache = false ;
1725
1784
@@ -1750,19 +1809,8 @@ private object FetchResource(
1750
1809
{
1751
1810
// Cache the deferredResourceReference so that it can be validated
1752
1811
// in case of a dictionary change prior to its inflation
1753
- _deferredResourceReferencesList ??= new DeferredResourceReferenceList ( ) ;
1754
-
1755
- if ( _deferredResourceReferencesList . Get ( resourceKey ) is { } existingDeferredResourceReference
1756
- && existingDeferredResourceReference . Dictionary == this )
1757
- {
1758
- deferredResourceReference = existingDeferredResourceReference ;
1759
- }
1760
- else
1761
- {
1762
- deferredResourceReference = _ownerApps is not null ? new DeferredAppResourceReference ( this , resourceKey ) : new DeferredResourceReference ( this , resourceKey ) ;
1763
-
1764
- _deferredResourceReferencesList . AddOrSet ( deferredResourceReference ) ;
1765
- }
1812
+ deferredResourceReference = _ownerApps is not null ? new DeferredAppResourceReference ( this , resourceKey ) : new DeferredResourceReference ( this , resourceKey ) ;
1813
+ GetOrCreateWeakReferenceList ( resourceKey ) . Add ( deferredResourceReference , true /*SkipFind*/ ) ;
1766
1814
}
1767
1815
}
1768
1816
else
@@ -1779,6 +1827,35 @@ private object FetchResource(
1779
1827
return GetValue ( resourceKey , out canCache ) ;
1780
1828
}
1781
1829
1830
+ private WeakReferenceList GetOrCreateWeakReferenceList ( object resourceKey )
1831
+ {
1832
+ this . _weakDeferredResourceReferencesMap ??= new ( ) ;
1833
+
1834
+ if ( ! this . _weakDeferredResourceReferencesMap . TryGetValue ( resourceKey , out var weakDeferredResourceReferences ) )
1835
+ {
1836
+ weakDeferredResourceReferences = new WeakReferenceList ( ) ;
1837
+ this . _weakDeferredResourceReferencesMap [ resourceKey ] = weakDeferredResourceReferences ;
1838
+ }
1839
+
1840
+ return weakDeferredResourceReferences ;
1841
+ }
1842
+
1843
+ internal void RemoveDeferredResourceReference ( DeferredResourceReference deferredResourceReference )
1844
+ {
1845
+ if ( FrameworkAppContextSwitches . DisableDynamicResourceOptimization )
1846
+ {
1847
+ _weakDeferredResourceReferences ? . Remove ( deferredResourceReference ) ;
1848
+ }
1849
+ else
1850
+ {
1851
+ //GetWeakReferenceList(deferredResourceReference.Key)?.Remove(deferredResourceReference);
1852
+ if ( this . _weakDeferredResourceReferencesMap ? . TryGetValue ( deferredResourceReference . Key , out var weakDeferredResourceReferences ) is true )
1853
+ {
1854
+ weakDeferredResourceReferences . Remove ( deferredResourceReference ) ;
1855
+ }
1856
+ }
1857
+ }
1858
+
1782
1859
/// <summary>
1783
1860
/// Validate the deferredResourceReference with the given key. Key could be null meaning
1784
1861
/// some catastrophic operation occurred so simply validate all DeferredResourceReferences
@@ -1804,34 +1881,45 @@ private void ValidateDeferredResourceReferences(object resourceKey)
1804
1881
}
1805
1882
else
1806
1883
{
1807
- if ( _deferredResourceReferencesList is null )
1884
+ if ( _weakDeferredResourceReferencesMap is null )
1808
1885
{
1809
1886
return ;
1810
1887
}
1811
1888
1812
1889
if ( resourceKey is null )
1813
1890
{
1814
- foreach ( DeferredResourceReference deferredResourceReference in _deferredResourceReferencesList )
1891
+ foreach ( var weakDeferredResourceReferences in _weakDeferredResourceReferencesMap . Values )
1815
1892
{
1816
- Inflate ( deferredResourceReference ) ;
1893
+ foreach ( var weakResourceReference in weakDeferredResourceReferences )
1894
+ {
1895
+ DeferredResourceReference deferredResourceReference = weakResourceReference as DeferredResourceReference ;
1896
+
1897
+ Inflate ( deferredResourceReference ) ;
1898
+ }
1817
1899
}
1818
1900
}
1819
1901
else
1820
1902
{
1821
- DeferredResourceReference deferredResourceReference = _deferredResourceReferencesList . Get ( resourceKey ) ;
1903
+ if ( _weakDeferredResourceReferencesMap . TryGetValue ( resourceKey , out var weakDeferredResourceReferences ) )
1904
+ {
1905
+ foreach ( var weakResourceReference in weakDeferredResourceReferences )
1906
+ {
1907
+ DeferredResourceReference deferredResourceReference = weakResourceReference as DeferredResourceReference ;
1822
1908
1823
- Inflate ( deferredResourceReference ) ;
1909
+ Inflate ( deferredResourceReference ) ;
1910
+ }
1911
+ }
1824
1912
}
1913
+ }
1825
1914
1826
- return ;
1915
+ return ;
1827
1916
1828
- void Inflate ( DeferredResourceReference deferredResourceReference )
1829
- {
1830
- // This will inflate the deferred reference, causing it
1831
- // to be removed from the list. The list may also be
1832
- // purged of dead references.
1833
- deferredResourceReference ? . GetValue ( BaseValueSourceInternal . Unknown ) ;
1834
- }
1917
+ void Inflate ( DeferredResourceReference deferredResourceReference )
1918
+ {
1919
+ // This will inflate the deferred reference, causing it
1920
+ // to be removed from the list. The list may also be
1921
+ // purged of dead references.
1922
+ deferredResourceReference ? . GetValue ( BaseValueSourceInternal . Unknown ) ;
1835
1923
}
1836
1924
}
1837
1925
@@ -2095,20 +2183,6 @@ internal WeakReferenceList ApplicationOwners
2095
2183
2096
2184
#endregion HelperMethods
2097
2185
2098
- #region Properties
2099
-
2100
- internal WeakReferenceList WeakDeferredResourceReferences
2101
- {
2102
- get { return _weakDeferredResourceReferences ; }
2103
- }
2104
-
2105
- internal DeferredResourceReferenceList DeferredResourceReferencesList
2106
- {
2107
- get { return _deferredResourceReferencesList ; }
2108
- }
2109
-
2110
- #endregion Properties
2111
-
2112
2186
#region Enumeration
2113
2187
2114
2188
/// <summary>
@@ -2519,11 +2593,11 @@ private void CopyDeferredContentFrom(ResourceDictionary loadedRD)
2519
2593
IsUnsafe = loadedRD . IsUnsafe ;
2520
2594
}
2521
2595
2522
- private void MoveDeferredResourceReferencesFrom ( ResourceDictionary loadedRD )
2596
+ private void MoveDeferredResourceReferencesFrom ( ResourceDictionary loadedRD )
2523
2597
{
2524
2598
if ( FrameworkAppContextSwitches . DisableDynamicResourceOptimization )
2525
2599
{
2526
- // copy the list
2600
+ // move the list
2527
2601
_weakDeferredResourceReferences = loadedRD . _weakDeferredResourceReferences ;
2528
2602
2529
2603
// redirect each entry toward its new owner
@@ -2537,11 +2611,20 @@ private void MoveDeferredResourceReferencesFrom(ResourceDictionary loadedRD)
2537
2611
}
2538
2612
else
2539
2613
{
2540
- // copy the list
2541
- _deferredResourceReferencesList = loadedRD . _deferredResourceReferencesList ;
2614
+ // move the map and thus the lists
2615
+ _weakDeferredResourceReferencesMap = loadedRD . _weakDeferredResourceReferencesMap ;
2542
2616
2543
- // redirect each entry toward its new owner
2544
- _deferredResourceReferencesList ? . ChangeDictionary ( this ) ;
2617
+ if ( _weakDeferredResourceReferencesMap is not null )
2618
+ {
2619
+ // redirect each entry toward its new owner
2620
+ foreach ( var weakDeferredResourceReferences in _weakDeferredResourceReferencesMap . Values )
2621
+ {
2622
+ foreach ( DeferredResourceReference drr in weakDeferredResourceReferences )
2623
+ {
2624
+ drr . Dictionary = this ;
2625
+ }
2626
+ }
2627
+ }
2545
2628
}
2546
2629
}
2547
2630
@@ -2609,7 +2692,7 @@ private enum FallbackState
2609
2692
private WeakReferenceList _ownerFCEs = null ;
2610
2693
private WeakReferenceList _ownerApps = null ;
2611
2694
private WeakReferenceList _weakDeferredResourceReferences = null ;
2612
- private DeferredResourceReferenceList _deferredResourceReferencesList = null ;
2695
+ private Dictionary < object , WeakReferenceList > _weakDeferredResourceReferencesMap = null ;
2613
2696
private ObservableCollection < ResourceDictionary > _mergedDictionaries = null ;
2614
2697
private Uri _source = null ;
2615
2698
private Uri _baseUri = null ;
0 commit comments