Skip to content
This repository was archived by the owner on Nov 20, 2018. It is now read-only.

Commit e3f921a

Browse files
committed
#339 Reduce IFeatureCollection surface area.
1 parent 5d7ec0e commit e3f921a

File tree

10 files changed

+177
-335
lines changed

10 files changed

+177
-335
lines changed

src/Microsoft.AspNet.Http.Features/FeatureCollection.cs

Lines changed: 41 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@
44
using System;
55
using System.Collections;
66
using System.Collections.Generic;
7+
using System.Linq;
78
using Microsoft.Framework.Internal;
89

910
namespace Microsoft.AspNet.Http.Features
1011
{
1112
public class FeatureCollection : IFeatureCollection
1213
{
13-
private readonly IFeatureCollection _defaults;
14+
private static KeyComparer FeatureKeyComparer = new FeatureCollection.KeyComparer();
1415
private readonly IDictionary<Type, object> _featureByFeatureType = new Dictionary<Type, object>();
15-
private readonly object _containerSync = new object();
16+
private readonly IFeatureCollection _defaults;
1617
private volatile int _containerRevision;
1718

1819
public FeatureCollection()
@@ -24,143 +25,78 @@ public FeatureCollection(IFeatureCollection defaults)
2425
_defaults = defaults;
2526
}
2627

27-
public object GetInterface()
28+
public virtual int Revision
2829
{
29-
return GetInterface(null);
30+
get { return _containerRevision + (_defaults?.Revision ?? 0); }
3031
}
3132

32-
public object GetInterface([NotNull] Type type)
33-
{
34-
object feature;
35-
if (_featureByFeatureType.TryGetValue(type, out feature))
36-
{
37-
return feature;
38-
}
33+
public bool IsReadOnly { get { return false; } }
3934

40-
if (_defaults != null && _defaults.TryGetValue(type, out feature))
41-
{
42-
return feature;
43-
}
44-
return null;
45-
}
46-
47-
void SetInterface([NotNull] Type type, object feature)
35+
public object this[[NotNull] Type key]
4836
{
49-
if (feature == null)
50-
{
51-
Remove(type);
52-
return;
53-
}
54-
55-
lock (_containerSync)
56-
{
57-
_featureByFeatureType[type] = feature;
58-
_containerRevision++;
59-
}
37+
get { return Get(key); }
38+
set { Set(key, value); }
6039
}
6140

62-
public virtual int Revision
41+
public object Get([NotNull] Type key)
6342
{
64-
get { return _containerRevision; }
43+
object result;
44+
return _featureByFeatureType.TryGetValue(key, out result) ? result : _defaults?.Get(key);
6545
}
6646

67-
public void Dispose()
47+
public void Set([NotNull] Type key, object value)
6848
{
69-
}
49+
if (value == null)
50+
{
51+
if (_featureByFeatureType.Remove(key))
52+
{
53+
_containerRevision++;
54+
}
55+
return;
56+
}
7057

71-
public IEnumerator<KeyValuePair<Type, object>> GetEnumerator()
72-
{
73-
throw new NotImplementedException();
58+
_featureByFeatureType[key] = value;
59+
_containerRevision++;
7460
}
7561

7662
IEnumerator IEnumerable.GetEnumerator()
7763
{
7864
return GetEnumerator();
7965
}
8066

81-
public void Add(KeyValuePair<Type, object> item)
82-
{
83-
SetInterface(item.Key, item.Value);
84-
}
85-
86-
public void Clear()
87-
{
88-
throw new NotImplementedException();
89-
}
90-
91-
public bool Contains(KeyValuePair<Type, object> item)
92-
{
93-
object value;
94-
return TryGetValue(item.Key, out value) && Equals(item.Value, value);
95-
}
96-
97-
public void CopyTo(KeyValuePair<Type, object>[] array, int arrayIndex)
98-
{
99-
throw new NotImplementedException();
100-
}
101-
102-
public bool Remove(KeyValuePair<Type, object> item)
103-
{
104-
return Contains(item) && Remove(item.Key);
105-
}
106-
107-
public int Count
108-
{
109-
get { throw new NotImplementedException(); }
110-
}
111-
112-
public bool IsReadOnly
113-
{
114-
get { return false; }
115-
}
116-
117-
public bool ContainsKey([NotNull] Type key)
118-
{
119-
return GetInterface(key) != null;
120-
}
121-
122-
public void Add([NotNull] Type key, [NotNull] object value)
67+
public IEnumerator<KeyValuePair<Type, object>> GetEnumerator()
12368
{
124-
if (ContainsKey(key))
69+
foreach (var pair in _featureByFeatureType)
12570
{
126-
throw new ArgumentException();
71+
yield return pair;
12772
}
128-
SetInterface(key, value);
129-
}
13073

131-
public bool Remove([NotNull] Type key)
132-
{
133-
lock (_containerSync)
74+
if (_defaults != null)
13475
{
135-
if (_featureByFeatureType.Remove(key))
76+
// Don't return features masked by the wrapper.
77+
foreach (var pair in _defaults.Except(_featureByFeatureType, FeatureKeyComparer))
13678
{
137-
_containerRevision++;
138-
return true;
79+
yield return pair;
13980
}
140-
return false;
14181
}
14282
}
14383

144-
public bool TryGetValue([NotNull] Type key, out object value)
145-
{
146-
value = GetInterface(key);
147-
return value != null;
148-
}
149-
150-
public object this[Type key]
84+
public virtual void Dispose()
15185
{
152-
get { return GetInterface(key); }
153-
set { SetInterface(key, value); }
86+
_defaults?.Dispose();
15487
}
15588

156-
public ICollection<Type> Keys
89+
private class KeyComparer : IEqualityComparer<KeyValuePair<Type, object>>
15790
{
158-
get { throw new NotImplementedException(); }
159-
}
91+
public bool Equals(KeyValuePair<Type, object> x, KeyValuePair<Type, object> y)
92+
{
93+
return x.Key.Equals(y.Key);
94+
}
16095

161-
public ICollection<object> Values
162-
{
163-
get { throw new NotImplementedException(); }
96+
public int GetHashCode(KeyValuePair<Type, object> obj)
97+
{
98+
throw new NotImplementedException();
99+
}
164100
}
165101
}
166102
}

src/Microsoft.AspNet.Http.Features/FeatureReference.cs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,19 @@ private FeatureReference(T feature, int revision)
1818

1919
public T Fetch(IFeatureCollection features)
2020
{
21-
if (_revision == features.Revision) return _feature;
22-
object value;
23-
if (features.TryGetValue(typeof(T), out value))
21+
if (_revision == features.Revision)
2422
{
25-
_feature = (T)value;
26-
}
27-
else
28-
{
29-
_feature = default(T);
23+
return _feature;
3024
}
25+
_feature = (T)features[typeof(T)];
3126
_revision = features.Revision;
3227
return _feature;
3328
}
3429

3530
public T Update(IFeatureCollection features, T feature)
3631
{
37-
features[typeof(T)] = _feature = feature;
32+
features[typeof(T)] = feature;
33+
_feature = feature;
3834
_revision = features.Revision;
3935
return feature;
4036
}

src/Microsoft.AspNet.Http.Features/IFeatureCollection.cs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,42 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using Microsoft.Framework.Internal;
67

78
namespace Microsoft.AspNet.Http.Features
89
{
9-
public interface IFeatureCollection : IDictionary<Type, object>, IDisposable
10+
public interface IFeatureCollection : IEnumerable<KeyValuePair<Type, object>>, IDisposable
1011
{
12+
/// <summary>
13+
/// Indicates if the collection can be modified.
14+
/// </summary>
15+
bool IsReadOnly { get; }
16+
17+
/// <summary>
18+
/// Incremented for each modification and can be used verify cached results.
19+
/// </summary>
1120
int Revision { get; }
21+
22+
/// <summary>
23+
/// Gets or sets a given feature. Setting a null value removes the feature.
24+
/// </summary>
25+
/// <param name="key"></param>
26+
/// <returns>The requested feature, or null if it is not present.</returns>
27+
object this[[NotNull] Type key] { get; set; }
28+
29+
/// <summary>
30+
/// Gets the requested feature, or null if it is not present.
31+
/// </summary>
32+
/// <param name="key"></param>
33+
/// <returns></returns>
34+
object Get([NotNull] Type key);
35+
36+
/// <summary>
37+
/// Sets the given feature, overriding the existing feature if any. If a null value is
38+
/// provided then any existing feature is removed.
39+
/// </summary>
40+
/// <param name="key"></param>
41+
/// <param name="value"></param>
42+
void Set([NotNull] Type key, object value);
1243
}
1344
}

src/Microsoft.AspNet.Http.Features/project.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"dnxcore50": {
1414
"dependencies": {
1515
"System.Collections": "4.0.10-beta-*",
16+
"System.Linq": "4.0.0-beta-*",
1617
"System.Net.Primitives": "4.0.10-beta-*",
1718
"System.Net.WebSockets": "4.0.0-beta-*",
1819
"System.Runtime.Extensions": "4.0.10-beta-*",

src/Microsoft.AspNet.Http/DefaultHttpContext.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,7 @@ public override void Dispose()
172172

173173
public override object GetFeature(Type type)
174174
{
175-
object value;
176-
return _features.TryGetValue(type, out value) ? value : null;
175+
return _features[type];
177176
}
178177

179178
public override void SetFeature(Type type, object instance)

0 commit comments

Comments
 (0)