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

Commit ac945a0

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

File tree

10 files changed

+162
-337
lines changed

10 files changed

+162
-337
lines changed

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

Lines changed: 46 additions & 107 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
{
14+
private static KeyComparer FeatureKeyComparer = new FeatureCollection.KeyComparer();
1315
private readonly IFeatureCollection _defaults;
14-
private readonly IDictionary<Type, object> _featureByFeatureType = new Dictionary<Type, object>();
15-
private readonly object _containerSync = new object();
16+
private IDictionary<Type, object> _features;
1617
private volatile int _containerRevision;
1718

1819
public FeatureCollection()
@@ -24,143 +25,81 @@ 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-
}
39-
40-
if (_defaults != null && _defaults.TryGetValue(type, out feature))
41-
{
42-
return feature;
43-
}
44-
return null;
45-
}
33+
public bool IsReadOnly { get { return false; } }
4634

47-
void SetInterface([NotNull] Type type, object feature)
35+
public object this[[NotNull] Type key]
4836
{
49-
if (feature == null)
37+
get
5038
{
51-
Remove(type);
52-
return;
39+
object result;
40+
return _features != null && _features.TryGetValue(key, out result) ? result : _defaults?[key];
5341
}
54-
55-
lock (_containerSync)
42+
set
5643
{
57-
_featureByFeatureType[type] = feature;
44+
if (value == null)
45+
{
46+
if (_features != null && _features.Remove(key))
47+
{
48+
_containerRevision++;
49+
}
50+
return;
51+
}
52+
53+
if (_features == null)
54+
{
55+
_features = new Dictionary<Type, object>();
56+
}
57+
_features[key] = value;
5858
_containerRevision++;
5959
}
6060
}
6161

62-
public virtual int Revision
63-
{
64-
get { return _containerRevision; }
65-
}
66-
67-
public void Dispose()
68-
{
69-
}
70-
71-
public IEnumerator<KeyValuePair<Type, object>> GetEnumerator()
72-
{
73-
throw new NotImplementedException();
74-
}
75-
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+
if (_features != null)
12570
{
126-
throw new ArgumentException();
71+
foreach (var pair in _features)
72+
{
73+
yield return pair;
74+
}
12775
}
128-
SetInterface(key, value);
129-
}
13076

131-
public bool Remove([NotNull] Type key)
132-
{
133-
lock (_containerSync)
77+
if (_defaults != null)
13478
{
135-
if (_featureByFeatureType.Remove(key))
79+
// Don't return features masked by the wrapper.
80+
foreach (var pair in _features == null ? _defaults : _defaults.Except(_features, FeatureKeyComparer))
13681
{
137-
_containerRevision++;
138-
return true;
82+
yield return pair;
13983
}
140-
return false;
14184
}
14285
}
14386

144-
public bool TryGetValue([NotNull] Type key, out object value)
87+
public virtual void Dispose()
14588
{
146-
value = GetInterface(key);
147-
return value != null;
89+
_defaults?.Dispose();
14890
}
14991

150-
public object this[Type key]
92+
private class KeyComparer : IEqualityComparer<KeyValuePair<Type, object>>
15193
{
152-
get { return GetInterface(key); }
153-
set { SetInterface(key, value); }
154-
}
155-
156-
public ICollection<Type> Keys
157-
{
158-
get { throw new NotImplementedException(); }
159-
}
94+
public bool Equals(KeyValuePair<Type, object> x, KeyValuePair<Type, object> y)
95+
{
96+
return x.Key.Equals(y.Key);
97+
}
16098

161-
public ICollection<object> Values
162-
{
163-
get { throw new NotImplementedException(); }
99+
public int GetHashCode(KeyValuePair<Type, object> obj)
100+
{
101+
throw new NotImplementedException();
102+
}
164103
}
165104
}
166105
}

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: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,27 @@
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; }
1228
}
1329
}

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)