-
Notifications
You must be signed in to change notification settings - Fork 12
/
FeatureCollection.cs
81 lines (67 loc) · 2.72 KB
/
FeatureCollection.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// Copyright (c) ZeroC, Inc.
using System.Collections;
namespace IceRpc.Features;
/// <summary>Default implementation of <see cref="IFeatureCollection" />.</summary>
public class FeatureCollection : IFeatureCollection
{
/// <summary>Gets a shared empty read-only instance.</summary>
/// <value>An empty <see cref="FeatureCollection" />.</value>
public static IFeatureCollection Empty { get; } = new FeatureCollection().AsReadOnly();
/// <summary>Gets a value indicating whether this feature collection is read-only or read-write.</summary>
/// <value>Always <see langword="false" /> with this class.</value>
public bool IsReadOnly => false;
private readonly IFeatureCollection? _defaults;
private readonly Dictionary<Type, object> _features = new();
/// <inheritdoc/>
public object? this[Type key]
{
get => _features.TryGetValue(key, out object? value) ? value : _defaults?[key];
set
{
if (value is null)
{
_ = _features.Remove(key);
}
else
{
_features[key] = value;
}
}
}
/// <summary>Constructs an empty read-write feature collection.</summary>
public FeatureCollection()
{
}
/// <summary>Constructs an empty read-write feature collection with defaults.</summary>
/// <param name="defaults">The feature collection that provide default values.</param>
public FeatureCollection(IFeatureCollection defaults) =>
// no need to query the empty read-only collection for defaults; any other feature collection (even empty and
// read-only) can change over time
_defaults = defaults == Empty ? null : defaults;
/// <inheritdoc/>
public TFeature? Get<TFeature>() => this[typeof(TFeature)] is object value ? (TFeature)value : default;
/// <inheritdoc />
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
/// <summary>Returns an enumerator that iterates over this feature collection.</summary>
/// <returns>An <see cref="IEnumerator{T}"/> object that can be used to iterate through this feature collection.
/// </returns>
public IEnumerator<KeyValuePair<Type, object>> GetEnumerator()
{
foreach (KeyValuePair<Type, object> pair in _features)
{
yield return pair;
}
if (_defaults is not null)
{
foreach (KeyValuePair<Type, object> pair in _defaults)
{
if (!_features.ContainsKey(pair.Key))
{
yield return pair;
}
}
}
}
/// <inheritdoc/>
public void Set<TFeature>(TFeature? feature) => this[typeof(TFeature)] = feature;
}