// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Web.Http.Properties;
namespace System.Web.Http
{
///
/// Extension methods for .
///
[EditorBrowsable(EditorBrowsableState.Never)]
internal static class DictionaryExtensions
{
///
/// Gets the value of associated with the specified key or default value if
/// either the key is not present or the value is not of type .
///
/// The type of the value associated with the specified key.
/// The instance where TValue is object.
/// The key whose value to get.
/// 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.
/// true if key was found, value is non-null, and value is of type ; otherwise false.
public static bool TryGetValue(this IDictionary collection, string key, out T value)
{
if (collection == null)
{
throw Error.ArgumentNull("collection");
}
object valueObj;
if (collection.TryGetValue(key, out valueObj))
{
if (valueObj is T)
{
value = (T)valueObj;
return true;
}
}
value = default(T);
return false;
}
///
/// Gets the value of associated with the specified key or throw an
/// if either the key is not present or the value is not of type .
///
/// The instance where TValue is object.
/// The key whose value to get.
/// An instance of type .
public static T GetValue(this IDictionary collection, string key)
{
if (collection == null)
{
throw Error.ArgumentNull("collection");
}
T value;
if (collection.TryGetValue(key, out value))
{
return value;
}
throw Error.InvalidOperation(CommonWebApiResources.DictionaryMissingRequiredValue, collection.GetType().Name, key, typeof(T).Name);
}
internal static IEnumerable> FindKeysWithPrefix(this IDictionary dictionary, string prefix)
{
if (dictionary == null)
{
throw Error.ArgumentNull("dictionary");
}
if (prefix == null)
{
throw Error.ArgumentNull("prefix");
}
TValue exactMatchValue;
if (dictionary.TryGetValue(prefix, out exactMatchValue))
{
yield return new KeyValuePair(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;
}
}
}
}
internal static bool DoesAnyKeyHavePrefix(this IDictionary dictionary, string prefix)
{
return FindKeysWithPrefix(dictionary, prefix).Any();
}
///
/// Adds a key/value pair of type to the
/// if the key does not already exist.
///
/// The actual type of the dictionary value.
/// A dictionary.
/// The key of the element to add.
/// The function used to generate a value for the .
/// The value for the key. This will be either the existing value for the if the key is already in the dictionary,
/// or the new value for the key as returned by if the key was not in the dictionary.
internal static T GetOrAdd(this ConcurrentDictionary