33using System . Collections . Generic ;
44using System . Linq ;
55using System . Reflection ;
6- using GetStateChangedPropertyDelegate = System . Func < object , Fluxor . IStateChangedNotifier > ;
6+ using GetStateChangedFieldDelegate = System . Func < object , Fluxor . IStateChangedNotifier > ;
77
88namespace Fluxor ;
99
10- /// <summary>
11- /// A utility class that automatically subscribes to all <see cref="IStateChangedNotifier"/> properties
12- /// on a specific object
13- /// </summary>
1410public static class StateSubscriber
1511{
16- private static readonly ConcurrentDictionary < Type , IEnumerable < GetStateChangedPropertyDelegate > > ValueDelegatesByType ;
12+ private static readonly ConcurrentDictionary < Type , IEnumerable < GetStateChangedFieldDelegate > > ValueDelegatesByType ;
1713
1814 static StateSubscriber ( )
19- {
20- ValueDelegatesByType = new ConcurrentDictionary < Type , IEnumerable < GetStateChangedPropertyDelegate > > ( ) ;
21- }
15+ => ValueDelegatesByType = new ConcurrentDictionary < Type , IEnumerable < GetStateChangedFieldDelegate > > ( ) ;
2216
2317 /// <summary>
24- /// Subscribes to all <see cref="IStateChangedNotifier"/> properties on the specified <paramref name="subject"/>
25- /// to ensure <paramref name="callback"/> is called whenever a state is modified
18+ /// Subscribes to all <see cref="IStateChangedNotifier"/> fields on the specified <paramref name="subject"/>
19+ /// to ensure <paramref name="callback"/> is called whenever a state is modified.
2620 /// </summary>
27- /// <param name="subject">The object to scan for <see cref="IStateChangedNotifier"/> properties .</param>
28- /// <param name="callback">The action to execute when one of the states are modified</param>
21+ /// <param name="subject">The object to scan for <see cref="IStateChangedNotifier"/> fields .</param>
22+ /// <param name="callback">The action to execute when one of the states are modified. </param>
2923 /// <returns></returns>
3024 public static IDisposable Subscribe ( object subject , Action < IStateChangedNotifier > callback )
3125 {
@@ -34,14 +28,15 @@ public static IDisposable Subscribe(object subject, Action<IStateChangedNotifier
3428 if ( callback is null )
3529 throw new ArgumentNullException ( nameof ( callback ) ) ;
3630
37- IEnumerable < GetStateChangedPropertyDelegate > getStateChangedNotifierPropertyDelegates =
38- GetStateChangedNotifierPropertyDelegatesForType ( subject . GetType ( ) ) ;
31+ IEnumerable < GetStateChangedFieldDelegate > getStateChangedNotifierFieldDelegates =
32+ GetStateChangedNotifierFieldDelegatesForType ( subject . GetType ( ) ) ;
33+
3934 var subscriptions = new List < ( IStateChangedNotifier StateChangedNotifier , EventHandler Handler ) > ( ) ;
40-
41- foreach ( GetStateChangedPropertyDelegate getStateChangedNotifierPropertyValue in getStateChangedNotifierPropertyDelegates )
35+
36+ foreach ( GetStateChangedFieldDelegate getStateChangedNotifierFieldValue in getStateChangedNotifierFieldDelegates )
4237 {
43- IStateChangedNotifier stateChangedNotifier = getStateChangedNotifierPropertyValue ( subject ) ;
44- var handler = new EventHandler ( ( s , a ) => callback ( stateChangedNotifier ) ) ;
38+ IStateChangedNotifier stateChangedNotifier = getStateChangedNotifierFieldValue ( subject ) ;
39+ var handler = new EventHandler ( ( _ , __ ) => callback ( stateChangedNotifier ) ) ;
4540
4641 subscriptions . Add ( ( stateChangedNotifier , handler ) ) ;
4742 stateChangedNotifier . StateChanged += handler ;
@@ -50,34 +45,32 @@ public static IDisposable Subscribe(object subject, Action<IStateChangedNotifier
5045 return new DisposableCallback (
5146 id : $ "{ nameof ( StateSubscriber ) } .{ nameof ( Subscribe ) } / { subject . GetType ( ) . FullName } ",
5247 ( ) =>
53- {
54- foreach ( var subscription in subscriptions )
55- subscription . StateChangedNotifier . StateChanged -= subscription . Handler ;
56- } ) ;
48+ {
49+ foreach ( var subscription in subscriptions )
50+ subscription . StateChangedNotifier . StateChanged -= subscription . Handler ;
51+ } ) ;
5752 }
5853
59- private static IEnumerable < PropertyInfo > GetStateChangedNotifierProperties ( Type t ) =>
54+ private static IEnumerable < FieldInfo > GetStateChangedNotifierFields ( Type t ) =>
6055 t == typeof ( object )
61- ? Enumerable . Empty < PropertyInfo > ( )
62- : GetStateChangedNotifierProperties ( t . BaseType )
56+ ? Enumerable . Empty < FieldInfo > ( )
57+ : GetStateChangedNotifierFields ( t . BaseType )
6358 . Union (
64- t . GetProperties ( BindingFlags . Instance | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . DeclaredOnly )
65- . Where ( p => typeof ( IStateChangedNotifier ) . IsAssignableFrom ( p . PropertyType ) )
59+ t . GetFields ( BindingFlags . Instance | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . DeclaredOnly )
60+ . Where ( f => typeof ( IStateChangedNotifier ) . IsAssignableFrom ( f . FieldType ) )
6661 ) ;
6762
68- private static IEnumerable < GetStateChangedPropertyDelegate > GetStateChangedNotifierPropertyDelegatesForType ( Type type )
63+ private static IEnumerable < GetStateChangedFieldDelegate > GetStateChangedNotifierFieldDelegatesForType ( Type type )
6964 {
7065 return ValueDelegatesByType . GetOrAdd ( type , _ =>
7166 {
72- var delegates = new List < GetStateChangedPropertyDelegate > ( ) ;
73- IEnumerable < PropertyInfo > stateChangedNotifierProperties = GetStateChangedNotifierProperties ( type ) ;
67+ var delegates = new List < GetStateChangedFieldDelegate > ( ) ;
68+ IEnumerable < FieldInfo > stateChangedNotifierFields = GetStateChangedNotifierFields ( type ) ;
7469
75- foreach ( PropertyInfo currentProperty in stateChangedNotifierProperties )
70+ foreach ( FieldInfo currentField in stateChangedNotifierFields )
7671 {
77- Type getterMethod = typeof ( Func < , > ) . MakeGenericType ( type , currentProperty . PropertyType ) ;
78- var stronglyTypedDelegate = Delegate . CreateDelegate ( getterMethod , currentProperty . GetGetMethod ( true ) ) ;
79- var getValueDelegate = new GetStateChangedPropertyDelegate (
80- x => ( IStateChangedNotifier ) stronglyTypedDelegate . DynamicInvoke ( x ) ) ;
72+ var getValueDelegate = new GetStateChangedFieldDelegate (
73+ x => ( IStateChangedNotifier ) currentField . GetValue ( x ) ! ) ;
8174 delegates . Add ( getValueDelegate ) ;
8275 }
8376
0 commit comments