1- // Copyright (C) 2003-2010 Xtensive LLC.
2- // All rights reserved .
3- // For conditions of distribution and use, see license .
1+ // Copyright (C) 2009-2020 Xtensive LLC.
2+ // This code is distributed under MIT license terms .
3+ // See the License.txt file in the project root for more information .
44// Created by: Alexis Kochetov
55// Created: 2009.03.12
66
77using System ;
88using System . Collections ;
99using System . Collections . Generic ;
1010using System . Diagnostics ;
11- using Xtensive . Core ;
1211
1312
1413namespace Xtensive . Collections
@@ -21,8 +20,50 @@ namespace Xtensive.Collections
2120 /// </summary>
2221 [ Serializable ]
2322 [ DebuggerDisplay ( "Count = {Count}" ) ]
24- public class BindingCollection < TKey , TValue > : IEnumerable < KeyValuePair < TKey , TValue > >
23+ public class BindingCollection < TKey , TValue > : IReadOnlyCollection < KeyValuePair < TKey , TValue > >
2524 {
25+ public readonly ref struct BindingScope
26+ {
27+ public static BindingScope Empty => new BindingScope ( ) ;
28+
29+ private readonly BindingCollection < TKey , TValue > owner ;
30+ private readonly TKey key ;
31+ private readonly TValue prevValue ;
32+ private readonly bool prevValueExists ;
33+
34+ public void Dispose ( )
35+ {
36+ if ( owner == null ) {
37+ return ;
38+ }
39+
40+ if ( prevValueExists ) {
41+ if ( ! owner . permanentBindings . Contains ( key ) ) {
42+ owner . bindings [ key ] = prevValue ;
43+ }
44+ }
45+ else {
46+ if ( ! owner . permanentBindings . Contains ( key ) ) {
47+ owner . bindings . Remove ( key ) ;
48+ }
49+ }
50+ }
51+
52+ public BindingScope ( BindingCollection < TKey , TValue > owner , TKey key ) : this ( )
53+ {
54+ this . owner = owner ;
55+ this . key = key ;
56+ }
57+
58+ public BindingScope ( BindingCollection < TKey , TValue > owner , TKey key , TValue prevValue )
59+ {
60+ this . owner = owner ;
61+ this . key = key ;
62+ this . prevValue = prevValue ;
63+ prevValueExists = true ;
64+ }
65+ }
66+
2667 [ DebuggerBrowsable ( DebuggerBrowsableState . RootHidden ) ]
2768 private readonly Dictionary < TKey , TValue > bindings = new Dictionary < TKey , TValue > ( ) ;
2869 private readonly HashSet < TKey > permanentBindings = new HashSet < TKey > ( ) ;
@@ -32,7 +73,7 @@ public class BindingCollection<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TV
3273 /// </summary>
3374 public virtual int Count {
3475 [ DebuggerStepThrough ]
35- get { return bindings . Count ; }
76+ get => bindings . Count ;
3677 }
3778
3879 /// <summary>
@@ -41,7 +82,7 @@ public virtual int Count {
4182 /// <value></value>
4283 public virtual TValue this [ TKey key ] {
4384 [ DebuggerStepThrough ]
44- get { return bindings [ key ] ; }
85+ get => bindings [ key ] ;
4586 }
4687
4788 /// <summary>
@@ -51,24 +92,15 @@ public virtual TValue this[TKey key] {
5192 /// <param name="value">The value to bind.</param>
5293 /// <returns>Disposable object that will
5394 /// destroy the binding on its disposal.</returns>
54- public virtual IDisposable Add ( TKey key , TValue value )
95+ public virtual BindingScope Add ( TKey key , TValue value )
5596 {
56- TValue previous ;
57-
58- if ( bindings . TryGetValue ( key , out previous ) ) {
97+ if ( bindings . TryGetValue ( key , out var previous ) ) {
5998 bindings [ key ] = value ;
60- return new Disposable ( isDisposing => {
61- if ( ! permanentBindings . Contains ( key ) )
62- bindings [ key ] = previous ;
63- } ) ;
64- }
65- else {
66- bindings . Add ( key , value ) ;
67- return new Disposable ( isDisposing => {
68- if ( ! permanentBindings . Contains ( key ) )
69- bindings . Remove ( key ) ;
70- } ) ;
99+ return new BindingScope ( this , key , previous ) ;
71100 }
101+
102+ bindings . Add ( key , value ) ;
103+ return new BindingScope ( this , key ) ;
72104 }
73105
74106 /// <summary>
@@ -80,8 +112,9 @@ public virtual IDisposable Add(TKey key, TValue value)
80112 public virtual void PermanentAdd ( TKey key , TValue value )
81113 {
82114 bindings [ key ] = value ;
83- if ( ! permanentBindings . Contains ( key ) )
115+ if ( ! permanentBindings . Contains ( key ) ) {
84116 permanentBindings . Add ( key ) ;
117+ }
85118 }
86119
87120 /// <summary>
@@ -92,8 +125,10 @@ public virtual void PermanentAdd(TKey key, TValue value)
92125 /// <exception cref="KeyNotFoundException">Key isn't found.</exception>
93126 public virtual void ReplaceBound ( TKey key , TValue value )
94127 {
95- if ( ! bindings . ContainsKey ( key ) )
128+ if ( ! bindings . ContainsKey ( key ) ) {
96129 throw new KeyNotFoundException ( ) ;
130+ }
131+
97132 bindings [ key ] = value ;
98133 }
99134
@@ -108,45 +143,27 @@ public virtual void ReplaceBound(TKey key, TValue value)
108143 /// contains an element with the specified key;
109144 /// otherwise, <see langword="false" />.</returns>
110145 [ DebuggerStepThrough ]
111- public virtual bool TryGetValue ( TKey key , out TValue value )
112- {
113- return bindings . TryGetValue ( key , out value ) ;
114- }
146+ public virtual bool TryGetValue ( TKey key , out TValue value ) => bindings . TryGetValue ( key , out value ) ;
115147
116148 /// <summary>
117149 /// Gets the sequence of bound keys.
118150 /// </summary>
119151 /// <returns>The sequence of bound keys.</returns>
120152 public virtual IEnumerable GetKeys ( )
121153 {
122- foreach ( var key in bindings . Keys )
154+ foreach ( var key in bindings . Keys ) {
123155 yield return key ;
156+ }
124157 }
125158
126159 #region IEnumerable<...> methods
127160
128161 /// <inheritdoc/>
129- public virtual IEnumerator < KeyValuePair < TKey , TValue > > GetEnumerator ( )
130- {
131- return bindings . GetEnumerator ( ) ;
132- }
162+ public virtual IEnumerator < KeyValuePair < TKey , TValue > > GetEnumerator ( ) => bindings . GetEnumerator ( ) ;
133163
134164 /// <inheritdoc/>
135- IEnumerator IEnumerable . GetEnumerator ( )
136- {
137- return GetEnumerator ( ) ;
138- }
165+ IEnumerator IEnumerable . GetEnumerator ( ) => GetEnumerator ( ) ;
139166
140167 #endregion
141-
142-
143- // Constructors
144-
145- /// <summary>
146- /// Initializes new instance of this type.
147- /// </summary>
148- public BindingCollection ( )
149- {
150- }
151168 }
152169}
0 commit comments