forked from haoduotnt/aspnetwebstack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDictionaryExtensions.cs
124 lines (111 loc) · 4.84 KB
/
DictionaryExtensions.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.ComponentModel;
using System.Diagnostics.Contracts;
namespace System.Collections.Generic
{
/// <summary>
/// Extension methods for <see cref="IDictionary{TKey,TValue}"/>.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
internal static class DictionaryExtensions
{
/// <summary>
/// Remove entries from dictionary that match the removeCondition.
/// </summary>
public static void RemoveFromDictionary<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, Func<KeyValuePair<TKey, TValue>, bool> removeCondition)
{
// Pass the delegate as the state to avoid a delegate and closure
dictionary.RemoveFromDictionary((entry, innerCondition) =>
{
return innerCondition(entry);
},
removeCondition);
}
/// <summary>
/// Remove entries from dictionary that match the removeCondition.
/// </summary>
public static void RemoveFromDictionary<TKey, TValue, TState>(this IDictionary<TKey, TValue> dictionary, Func<KeyValuePair<TKey, TValue>, TState, bool> removeCondition, TState state)
{
Contract.Assert(dictionary != null);
Contract.Assert(removeCondition != null);
// Because it is not possible to delete while enumerating, a copy of the keys must be taken. Use the size of the dictionary as an upper bound
// to avoid creating more than one copy of the keys.
int removeCount = 0;
TKey[] keys = new TKey[dictionary.Count];
foreach (var entry in dictionary)
{
if (removeCondition(entry, state))
{
keys[removeCount] = entry.Key;
removeCount++;
}
}
for (int i = 0; i < removeCount; i++)
{
dictionary.Remove(keys[i]);
}
}
/// <summary>
/// Gets the value of <typeparamref name="T"/> associated with the specified key or <c>default</c> value if
/// either the key is not present or the value is not of type <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The type of the value associated with the specified key.</typeparam>
/// <param name="collection">The <see cref="IDictionary{TKey,TValue}"/> instance where <c>TValue</c> is <c>object</c>.</param>
/// <param name="key">The key whose value to get.</param>
/// <param name="value">When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the value parameter.</param>
/// <returns><c>true</c> if key was found, value is non-null, and value is of type <typeparamref name="T"/>; otherwise false.</returns>
public static bool TryGetValue<T>(this IDictionary<string, object> collection, string key, out T value)
{
Contract.Assert(collection != null);
object valueObj;
if (collection.TryGetValue(key, out valueObj))
{
if (valueObj is T)
{
value = (T)valueObj;
return true;
}
}
value = default(T);
return false;
}
internal static IEnumerable<KeyValuePair<string, TValue>> FindKeysWithPrefix<TValue>(this IDictionary<string, TValue> dictionary, string prefix)
{
Contract.Assert(dictionary != null);
Contract.Assert(prefix != null);
TValue exactMatchValue;
if (dictionary.TryGetValue(prefix, out exactMatchValue))
{
yield return new KeyValuePair<string, TValue>(prefix, exactMatchValue);
}
foreach (var entry in dictionary)
{
string key = entry.Key;
if (key.Length <= prefix.Length)
{
continue;
}
if (!key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
{
continue;
}
// Everything is prefixed by the empty string
if (prefix.Length == 0)
{
yield return entry;
}
else
{
char charAfterPrefix = key[prefix.Length];
switch (charAfterPrefix)
{
case '[':
case '.':
yield return entry;
break;
}
}
}
}
}
}