@@ -25,11 +25,11 @@ namespace Microsoft.AspNetCore.OData.Deltas
25
25
public class Delta < T > : Delta , IDelta , ITypedDelta where T : class
26
26
{
27
27
// cache property accessors for this type and all its derived types.
28
- private static ConcurrentDictionary < Type , Dictionary < string , PropertyAccessor < T > > > _propertyCache
28
+ private static readonly ConcurrentDictionary < Type , Dictionary < string , PropertyAccessor < T > > > _propertyCache
29
29
= new ConcurrentDictionary < Type , Dictionary < string , PropertyAccessor < T > > > ( ) ;
30
30
31
31
private Dictionary < string , PropertyAccessor < T > > _allProperties ;
32
- private HashSet < string > _updatableProperties ;
32
+ private List < string > _updatableProperties ;
33
33
34
34
private HashSet < string > _changedProperties ;
35
35
@@ -39,7 +39,7 @@ private static ConcurrentDictionary<Type, Dictionary<string, PropertyAccessor<T>
39
39
private T _instance ;
40
40
private Type _structuredType ;
41
41
42
- private PropertyInfo _dynamicDictionaryPropertyinfo ;
42
+ private readonly PropertyInfo _dynamicDictionaryPropertyinfo ;
43
43
private HashSet < string > _changedDynamicProperties ;
44
44
private IDictionary < string , object > _dynamicDictionaryCache ;
45
45
@@ -98,16 +98,19 @@ public Delta(Type structuralType, IEnumerable<string> updatableProperties,
98
98
99
99
/// <inheritdoc/>
100
100
public virtual Type StructuredType
101
- {
102
- get
103
- {
104
- return _structuredType ;
105
- }
106
- }
101
+ => _structuredType ;
107
102
108
103
/// <inheritdoc/>
109
104
public virtual Type ExpectedClrType => typeof ( T ) ;
110
105
106
+ /// <summary>
107
+ /// The list of property names that can be updated.
108
+ /// </summary>
109
+ /// <remarks>When the list is modified, any modified properties that were removed from the list are no longer
110
+ /// considered to be changed.</remarks>
111
+ public IList < string > UpdatableProperties
112
+ => _updatableProperties ;
113
+
111
114
/// <inheritdoc/>
112
115
public override void Clear ( )
113
116
{
@@ -172,7 +175,7 @@ public override bool TryGetPropertyValue(string name, out object value)
172
175
}
173
176
}
174
177
175
- if ( this . _deltaNestedResources . ContainsKey ( name ) )
178
+ if ( _deltaNestedResources . ContainsKey ( name ) )
176
179
{
177
180
// If this is a nested resource, get the value from the dictionary of nested resources.
178
181
object deltaNestedResource = _deltaNestedResources [ name ] ;
@@ -259,7 +262,7 @@ public T GetInstance()
259
262
/// </summary>
260
263
public override IEnumerable < string > GetChangedPropertyNames ( )
261
264
{
262
- return _changedProperties . Concat ( _deltaNestedResources . Keys ) ;
265
+ return _changedProperties . Intersect ( _updatableProperties ) . Concat ( _deltaNestedResources . Keys ) ;
263
266
}
264
267
265
268
/// <summary>
@@ -269,7 +272,8 @@ public override IEnumerable<string> GetChangedPropertyNames()
269
272
/// </summary>
270
273
public override IEnumerable < string > GetUnchangedPropertyNames ( )
271
274
{
272
- return _updatableProperties . Except ( GetChangedPropertyNames ( ) ) ;
275
+ // UpdatableProperties could include arbitrary strings, filter by _allProperties
276
+ return _updatableProperties . Intersect ( _allProperties . Keys ) . Except ( GetChangedPropertyNames ( ) ) ;
273
277
}
274
278
275
279
/// <summary>
@@ -295,7 +299,7 @@ public void CopyChangedValues(T original)
295
299
296
300
// For regular non-structural properties at current level.
297
301
PropertyAccessor < T > [ ] propertiesToCopy =
298
- this . _changedProperties . Select ( s => _allProperties [ s ] ) . ToArray ( ) ;
302
+ _changedProperties . Intersect ( _updatableProperties ) . Select ( s => _allProperties [ s ] ) . ToArray ( ) ;
299
303
foreach ( PropertyAccessor < T > propertyToCopy in propertiesToCopy )
300
304
{
301
305
propertyToCopy . Copy ( _instance , original ) ;
@@ -498,12 +502,11 @@ private void InitializeProperties(IEnumerable<string> updatableProperties)
498
502
499
503
if ( updatableProperties != null )
500
504
{
501
- _updatableProperties = new HashSet < string > ( updatableProperties ) ;
502
- _updatableProperties . IntersectWith ( _allProperties . Keys ) ;
505
+ _updatableProperties = updatableProperties . Intersect ( _allProperties . Keys ) . ToList ( ) ;
503
506
}
504
507
else
505
508
{
506
- _updatableProperties = new HashSet < string > ( _allProperties . Keys ) ;
509
+ _updatableProperties = new List < string > ( _allProperties . Keys ) ;
507
510
}
508
511
509
512
if ( _dynamicDictionaryPropertyinfo != null )
@@ -618,7 +621,7 @@ private bool TrySetPropertyValueInternal(string name, object value)
618
621
throw Error . ArgumentNull ( "name" ) ;
619
622
}
620
623
621
- if ( ! _updatableProperties . Contains ( name ) )
624
+ if ( ! ( _allProperties . ContainsKey ( name ) && _updatableProperties . Contains ( name ) ) )
622
625
{
623
626
return false ;
624
627
}
@@ -648,7 +651,7 @@ private bool TrySetNestedResourceInternal(string name, object deltaNestedResourc
648
651
throw Error . ArgumentNull ( "name" ) ;
649
652
}
650
653
651
- if ( ! _updatableProperties . Contains ( name ) )
654
+ if ( ! ( _allProperties . ContainsKey ( name ) && _updatableProperties . Contains ( name ) ) )
652
655
{
653
656
return false ;
654
657
}
0 commit comments