22{
33 using System ;
44 using System . Collections . Generic ;
5+ using System . Linq ;
56 using Microsoft . Extensions . Logging ;
67
78 public class Subscriptions
89 {
10+ private readonly struct Subscription : IEquatable < Subscription >
11+ {
12+ public Subscription ( Type aStateType , string aComponentId , WeakReference < BlazorStateComponent > aBlazorStateComponentReference )
13+ {
14+ StateType = aStateType ;
15+ ComponentId = aComponentId ;
16+ BlazorStateComponentReference = aBlazorStateComponentReference ;
17+ }
18+
19+ public Type StateType { get ; }
20+ public string ComponentId { get ; }
21+ public WeakReference < BlazorStateComponent > BlazorStateComponentReference { get ; }
22+
23+ public bool Equals ( Subscription aSubscription ) =>
24+ EqualityComparer < Type > . Default . Equals ( StateType , aSubscription . StateType ) &&
25+ ComponentId == aSubscription . ComponentId &&
26+ EqualityComparer < WeakReference < BlazorStateComponent > > . Default . Equals ( BlazorStateComponentReference , aSubscription . BlazorStateComponentReference ) ;
27+
28+ public static bool operator == ( Subscription aLeftSubscription , Subscription aRightSubscription ) => aLeftSubscription . Equals ( aRightSubscription ) ;
29+ public static bool operator != ( Subscription aLeftSubscription , Subscription aRightSubscription ) => ! ( aLeftSubscription == aRightSubscription ) ;
30+ }
31+
932 public Subscriptions ( ILogger < Subscriptions > aLogger )
1033 {
1134 Logger = aLogger ;
12- BlazorStateComponentReferencesDictionary = new Dictionary < Type , List < WeakReference < BlazorStateComponent > > > ( ) ;
35+ BlazorStateComponentReferencesList = new List < Subscription > ( ) ;
1336 }
1437
1538 private ILogger Logger { get ; }
16- private Dictionary < Type , List < WeakReference < BlazorStateComponent > > > BlazorStateComponentReferencesDictionary { get ; }
39+ private List < Subscription > BlazorStateComponentReferencesList { get ; }
1740
1841 public Subscriptions Add < T > ( BlazorStateComponent aBlazorStateComponent )
1942 {
@@ -23,18 +46,27 @@ public Subscriptions Add<T>(BlazorStateComponent aBlazorStateComponent)
2346 }
2447 public Subscriptions Add ( Type aType , BlazorStateComponent aBlazorStateComponent )
2548 {
26-
27- if ( ! ( BlazorStateComponentReferencesDictionary . TryGetValue ( aType , out List < WeakReference < BlazorStateComponent > > blazorStateComponentReferences ) ) )
49+ // Add only once.
50+ if ( ! BlazorStateComponentReferencesList . Any ( aSubscription => aSubscription . StateType == aType && aSubscription . ComponentId == aBlazorStateComponent . Id ) )
2851 {
29- blazorStateComponentReferences = new List < WeakReference < BlazorStateComponent > > ( ) ;
30- BlazorStateComponentReferencesDictionary . Add ( aType , blazorStateComponentReferences ) ;
31- }
52+ var subscription = new Subscription (
53+ aType ,
54+ aBlazorStateComponent . Id ,
55+ new WeakReference < BlazorStateComponent > ( aBlazorStateComponent ) ) ;
3256
33- blazorStateComponentReferences . Add ( new WeakReference < BlazorStateComponent > ( aBlazorStateComponent ) ) ;
57+ BlazorStateComponentReferencesList . Add ( subscription ) ;
58+ }
3459
3560 return this ;
3661 }
3762
63+ public Subscriptions Remove ( BlazorStateComponent aBlazorStateComponent )
64+ {
65+ Logger . LogDebug ( $ "Removing Subscription for { aBlazorStateComponent . Id } ") ;
66+ BlazorStateComponentReferencesList . RemoveAll ( aRecord => aRecord . ComponentId == aBlazorStateComponent . Id ) ;
67+
68+ return this ;
69+ }
3870 /// <summary>
3971 /// Will iterate over all subscriptions for the given type and call ReRender on each.
4072 /// If the target component no longer exists it will remove its subscription.
@@ -54,27 +86,31 @@ public void ReRenderSubscribers<T>()
5486 /// <param name="aType"></param>
5587 public void ReRenderSubscribers ( Type aType )
5688 {
57- //GC.Collect(); // I added the collect to test that I am not holding strong references and they were collected.
58- bool isAny = BlazorStateComponentReferencesDictionary . TryGetValue ( aType , out List < WeakReference < BlazorStateComponent > > blazorStateblazorStateComponentReferencesComponents ) ;
59- if ( isAny )
89+ IEnumerable < Subscription > subscriptions = BlazorStateComponentReferencesList . Where ( aRecord => aRecord . StateType == aType ) ;
90+ foreach ( Subscription subscription in subscriptions )
6091 {
61- Logger . LogDebug ( $ "ReRendering { blazorStateblazorStateComponentReferencesComponents . Count } Subscribers for state of type: { aType . Name } ") ;
62- WeakReference < BlazorStateComponent > [ ] blazorStateComponentReferencesArray = blazorStateblazorStateComponentReferencesComponents . ToArray ( ) ;
63-
64- foreach ( WeakReference < BlazorStateComponent > aBlazorStateComponentReference in blazorStateComponentReferencesArray )
92+ if ( subscription . BlazorStateComponentReference . TryGetTarget ( out BlazorStateComponent target ) )
6593 {
66- if ( aBlazorStateComponentReference . TryGetTarget ( out BlazorStateComponent target ) )
67- {
68- Logger . LogDebug ( $ "ReRender: { target . GetType ( ) . Name } ") ;
69- target . ReRender ( ) ;
70- }
71- else
72- {
73- Logger . LogDebug ( $ "Removing subscription to previously destroyed component.") ;
74- blazorStateblazorStateComponentReferencesComponents . Remove ( aBlazorStateComponentReference ) ;
75- }
94+ Logger . LogDebug ( $ "ReRender: { target . GetType ( ) . Name } ") ;
95+ target . ReRender ( ) ;
96+ }
97+ else
98+ {
99+ // If Dispose is called will I ever have items in this list that got Garbage collected?
100+ // Maybe for those that don't inherit from our BaseComponent.
101+ BlazorStateComponentReferencesList . Remove ( subscription ) ;
76102 }
77103 }
78104 }
105+
106+ public override bool Equals ( object obj ) => obj is Subscriptions subscriptions && EqualityComparer < ILogger > . Default . Equals ( Logger , subscriptions . Logger ) && EqualityComparer < List < Subscription > > . Default . Equals ( BlazorStateComponentReferencesList , subscriptions . BlazorStateComponentReferencesList ) ;
107+
108+ public override int GetHashCode ( )
109+ {
110+ var hashCode = - 914156548 ;
111+ hashCode = hashCode * - 1521134295 + EqualityComparer < ILogger > . Default . GetHashCode ( Logger ) ;
112+ hashCode = hashCode * - 1521134295 + EqualityComparer < List < Subscription > > . Default . GetHashCode ( BlazorStateComponentReferencesList ) ;
113+ return hashCode ;
114+ }
79115 }
80116}
0 commit comments