33using System . Linq . Expressions ;
44using System . Reflection ;
55
6- namespace Eocron . Algorithms . UI . Editing
6+ namespace Eocron . Algorithms . UI . Editing ;
7+
8+ public class PropertyEditSessionChange < TDocument , TProperty > : IEditSessionChange < TDocument >
79{
8- public class PropertyEditSessionChange < TDocument , TProperty > : IEditSessionChange < TDocument >
10+ private readonly Expression < Func < TDocument , TProperty > > _propertySelector ;
11+ private readonly Action < object , PropertyInfo , EditSessionChangeContext > _onRedo ;
12+ private readonly Action < object , PropertyInfo , EditSessionChangeContext > _onUndo ;
13+ private readonly List < ( object parent , PropertyInfo property ) > _createdObjects = new ( ) ;
14+ private EditSessionChangeContext _context ;
15+
16+ public PropertyEditSessionChange (
17+ Expression < Func < TDocument , TProperty > > propertySelector ,
18+ Action < object , PropertyInfo , EditSessionChangeContext > onRedo ,
19+ Action < object , PropertyInfo , EditSessionChangeContext > onUndo )
920 {
10- private readonly Expression < Func < TDocument , TProperty > > _propertySelector ;
11- private readonly TProperty _newValue ;
12- private TProperty _oldValue ;
13- private readonly List < ( object parent , PropertyInfo property ) > _createdObjects = new ( ) ;
14-
15- public PropertyEditSessionChange (
16- Expression < Func < TDocument , TProperty > > propertySelector ,
17- TProperty newValue )
18- {
19- _propertySelector = propertySelector ?? throw new ArgumentNullException ( nameof ( propertySelector ) ) ;
20- _newValue = newValue ;
21- }
22-
23- public void Redo ( TDocument document )
24- {
25- if ( document == null ) throw new ArgumentNullException ( nameof ( document ) ) ;
21+ _propertySelector = propertySelector ?? throw new ArgumentNullException ( nameof ( propertySelector ) ) ;
22+ _onRedo = onRedo ;
23+ _onUndo = onUndo ;
24+ }
2625
27- var properties = GetPropertyChain ( _propertySelector ) ;
26+ public void Redo ( TDocument document )
27+ {
28+ if ( document == null ) throw new ArgumentNullException ( nameof ( document ) ) ;
2829
29- object current = document ;
30+ var properties = GetPropertyChain ( _propertySelector ) ;
3031
31- for ( var i = 0 ; i < properties . Count - 1 ; i ++ )
32- {
33- var prop = properties [ i ] ;
34- var value = prop . GetValue ( current ) ;
32+ object current = document ;
3533
36- if ( value == null )
37- {
38- value = Activator . CreateInstance ( prop . PropertyType )
39- ?? throw new InvalidOperationException (
40- $ "Cannot create instance of { prop . PropertyType . FullName } ") ;
34+ for ( var i = 0 ; i < properties . Count - 1 ; i ++ )
35+ {
36+ var prop = properties [ i ] ;
37+ var value = prop . GetValue ( current ) ;
4138
42- prop . SetValue ( current , value ) ;
43- _createdObjects . Add ( ( current , prop ) ) ;
44- }
39+ if ( value == null )
40+ {
41+ value = Activator . CreateInstance ( prop . PropertyType )
42+ ?? throw new InvalidOperationException (
43+ $ "Cannot create instance of { prop . PropertyType . FullName } ") ;
4544
46- current = value ;
45+ prop . SetValue ( current , value ) ;
46+ _createdObjects . Add ( ( current , prop ) ) ;
4747 }
4848
49- var targetProperty = properties [ ^ 1 ] ;
50- _oldValue = ( TProperty ) targetProperty . GetValue ( current ) ;
51-
52- targetProperty . SetValue ( current , _newValue ) ;
49+ current = value ;
5350 }
5451
55- public void Undo ( TDocument document )
56- {
57- var properties = GetPropertyChain ( _propertySelector ) ;
52+ _context = new EditSessionChangeContext ( ) ;
53+ _onRedo ( current , properties [ ^ 1 ] , _context ) ;
54+ }
5855
59- object current = document ;
56+ public void Undo ( TDocument document )
57+ {
58+ var properties = GetPropertyChain ( _propertySelector ) ;
6059
61- for ( int i = 0 ; i < properties . Count - 1 ; i ++ )
62- {
63- current = properties [ i ] . GetValue ( current ) ;
64- if ( current == null )
65- return ;
66- }
60+ object current = document ;
6761
68- properties [ ^ 1 ] . SetValue ( current , _oldValue ) ;
69-
70- for ( var i = _createdObjects . Count - 1 ; i >= 0 ; i -- )
71- {
72- var ( parent , property ) = _createdObjects [ i ] ;
73- property . SetValue ( parent , null ) ;
74- }
75- _createdObjects . Clear ( ) ;
62+ for ( int i = 0 ; i < properties . Count - 1 ; i ++ )
63+ {
64+ current = properties [ i ] . GetValue ( current ) ;
65+ if ( current == null )
66+ return ;
7667 }
7768
78- private static List < PropertyInfo > GetPropertyChain (
79- Expression < Func < TDocument , TProperty > > expression )
69+ _onUndo ( current , properties [ ^ 1 ] , _context ) ;
70+
71+ for ( var i = _createdObjects . Count - 1 ; i >= 0 ; i -- )
8072 {
81- var properties = new List < PropertyInfo > ( ) ;
82- Expression current = expression . Body ;
83-
84- while ( current is MemberExpression member )
85- {
86- if ( member . Member is PropertyInfo property )
87- properties . Insert ( 0 , property ) ;
88- else
89- throw new InvalidOperationException ( "Expression contains non-property member." ) ;
73+ var ( parent , property ) = _createdObjects [ i ] ;
74+ property . SetValue ( parent , null ) ;
75+ }
76+ _createdObjects . Clear ( ) ;
77+ }
9078
91- current = member . Expression ;
92- }
79+ private static List < PropertyInfo > GetPropertyChain (
80+ Expression < Func < TDocument , TProperty > > expression )
81+ {
82+ var properties = new List < PropertyInfo > ( ) ;
83+ Expression current = expression . Body ;
9384
94- if ( current . NodeType != ExpressionType . Parameter )
95- throw new InvalidOperationException ( "Invalid property selector expression." ) ;
85+ while ( current is MemberExpression member )
86+ {
87+ if ( member . Member is PropertyInfo property )
88+ properties . Insert ( 0 , property ) ;
89+ else
90+ throw new InvalidOperationException ( "Expression contains non-property member." ) ;
9691
97- return properties ;
92+ current = member . Expression ;
9893 }
94+
95+ if ( current . NodeType != ExpressionType . Parameter )
96+ throw new InvalidOperationException ( "Invalid property selector expression." ) ;
97+
98+ return properties ;
9999 }
100100}
0 commit comments