Skip to content

Commit 4699051

Browse files
authored
Delta does not allow UpdatableProperties to be changed (#2483)
1 parent 777e556 commit 4699051

7 files changed

Lines changed: 227 additions & 68 deletions

File tree

src/Microsoft.AspNet.OData.Shared/DeltaOfTStructuralType.cs

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@
88
using System;
99
using System.Collections.Concurrent;
1010
using System.Collections.Generic;
11-
using System.Diagnostics;
1211
using System.Diagnostics.CodeAnalysis;
1312
using System.Diagnostics.Contracts;
1413
using System.Linq;
1514
using System.Reflection;
1615
using System.Runtime.CompilerServices;
17-
using Microsoft.AspNet.OData.Builder.Conventions.Attributes;
1816
using Microsoft.AspNet.OData.Common;
1917
using Microsoft.AspNet.OData.Formatter;
2018

@@ -28,11 +26,11 @@ namespace Microsoft.AspNet.OData
2826
public class Delta<TStructuralType> : TypedDelta, IDelta where TStructuralType : class
2927
{
3028
// cache property accessors for this type and all its derived types.
31-
private static ConcurrentDictionary<Type, Dictionary<string, PropertyAccessor<TStructuralType>>> _propertyCache
29+
private static readonly ConcurrentDictionary<Type, Dictionary<string, PropertyAccessor<TStructuralType>>> _propertyCache
3230
= new ConcurrentDictionary<Type, Dictionary<string, PropertyAccessor<TStructuralType>>>();
3331

3432
private Dictionary<string, PropertyAccessor<TStructuralType>> _allProperties;
35-
private HashSet<string> _updatableProperties;
33+
private List<string> _updatableProperties;
3634

3735
private HashSet<string> _changedProperties;
3836

@@ -42,7 +40,7 @@ private static ConcurrentDictionary<Type, Dictionary<string, PropertyAccessor<TS
4240
private TStructuralType _instance;
4341
private Type _structuredType;
4442

45-
private PropertyInfo _dynamicDictionaryPropertyinfo;
43+
private readonly PropertyInfo _dynamicDictionaryPropertyinfo;
4644
private HashSet<string> _changedDynamicProperties;
4745
private IDictionary<string, object> _dynamicDictionaryCache;
4846

@@ -98,18 +96,19 @@ public Delta(Type structuralType, IEnumerable<string> updatableProperties,
9896

9997
/// <inheritdoc/>
10098
public override Type StructuredType
101-
{
102-
get
103-
{
104-
return _structuredType;
105-
}
106-
}
99+
=> _structuredType;
107100

108101
/// <inheritdoc/>
109102
public override Type ExpectedClrType
110-
{
111-
get { return typeof(TStructuralType); }
112-
}
103+
=> typeof(TStructuralType);
104+
105+
/// <summary>
106+
/// The list of property names that can be updated.
107+
/// </summary>
108+
/// <remarks>When the list is modified, any modified properties that were removed from the list are no longer
109+
/// considered to be changed.</remarks>
110+
public IList<string> UpdatableProperties
111+
=> _updatableProperties;
113112

114113
/// <inheritdoc/>
115114
public override void Clear()
@@ -120,7 +119,7 @@ public override void Clear()
120119
/// <inheritdoc/>
121120
public override bool TrySetPropertyValue(string name, object value)
122121
{
123-
if (string.IsNullOrWhiteSpace(name))
122+
if (String.IsNullOrWhiteSpace(name))
124123
{
125124
throw Error.ArgumentNull("name");
126125
}
@@ -175,7 +174,7 @@ public override bool TryGetPropertyValue(string name, out object value)
175174
}
176175
}
177176

178-
if (this._deltaNestedResources.ContainsKey(name))
177+
if (_deltaNestedResources.ContainsKey(name))
179178
{
180179
// If this is a nested resource, get the value from the dictionary of nested resources.
181180
object deltaNestedResource = _deltaNestedResources[name];
@@ -263,7 +262,7 @@ public TStructuralType GetInstance()
263262
/// </summary>
264263
public override IEnumerable<string> GetChangedPropertyNames()
265264
{
266-
return _changedProperties.Concat(_deltaNestedResources.Keys);
265+
return _changedProperties.Intersect(_updatableProperties).Concat(_deltaNestedResources.Keys);
267266
}
268267

269268
/// <summary>
@@ -273,7 +272,8 @@ public override IEnumerable<string> GetChangedPropertyNames()
273272
/// </summary>
274273
public override IEnumerable<string> GetUnchangedPropertyNames()
275274
{
276-
return _updatableProperties.Except(GetChangedPropertyNames());
275+
// UpdatableProperties could include arbitrary strings, filter by _allProperties
276+
return _updatableProperties.Intersect(_allProperties.Keys).Except(GetChangedPropertyNames());
277277
}
278278

279279
/// <summary>
@@ -299,7 +299,7 @@ public void CopyChangedValues(TStructuralType original)
299299

300300
// For regular non-structural properties at current level.
301301
PropertyAccessor<TStructuralType>[] propertiesToCopy =
302-
this._changedProperties.Select(s => _allProperties[s]).ToArray();
302+
_changedProperties.Intersect(_updatableProperties).Select(s => _allProperties[s]).ToArray();
303303
foreach (PropertyAccessor<TStructuralType> propertyToCopy in propertiesToCopy)
304304
{
305305
propertyToCopy.Copy(_instance, original);
@@ -509,12 +509,11 @@ private void InitializeProperties(IEnumerable<string> updatableProperties)
509509

510510
if (updatableProperties != null)
511511
{
512-
_updatableProperties = new HashSet<string>(updatableProperties);
513-
_updatableProperties.IntersectWith(_allProperties.Keys);
512+
_updatableProperties = updatableProperties.Intersect(_allProperties.Keys).ToList();
514513
}
515514
else
516515
{
517-
_updatableProperties = new HashSet<string>(_allProperties.Keys);
516+
_updatableProperties = new List<string>(_allProperties.Keys);
518517
}
519518

520519
if (_dynamicDictionaryPropertyinfo != null)
@@ -629,7 +628,7 @@ private bool TrySetPropertyValueInternal(string name, object value)
629628
throw Error.ArgumentNull("name");
630629
}
631630

632-
if (!_updatableProperties.Contains(name))
631+
if (!(_allProperties.ContainsKey(name) && _updatableProperties.Contains(name)))
633632
{
634633
return false;
635634
}
@@ -659,7 +658,7 @@ private bool TrySetNestedResourceInternal(string name, object deltaNestedResourc
659658
throw Error.ArgumentNull("name");
660659
}
661660

662-
if (!_updatableProperties.Contains(name))
661+
if (!(_allProperties.ContainsKey(name) && _updatableProperties.Contains(name)))
663662
{
664663
return false;
665664
}

0 commit comments

Comments
 (0)