// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace Microsoft.AspNet.Routing { /// /// An type for route values. /// public class RouteValueDictionary : IDictionary { private readonly Dictionary _dictionary; /// /// Creates an empty RouteValueDictionary. /// public RouteValueDictionary() { _dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); } /// /// Creates a RouteValueDictionary initialized with the provided input values. /// /// Input values to copy into the dictionary. public RouteValueDictionary([NotNull] IDictionary values) { _dictionary = new Dictionary(values, StringComparer.OrdinalIgnoreCase); } /// /// Creates a RouteValueDictionary initialized with the provided input values. /// /// Input values to copy into the dictionary. /// /// The input parameter is interpreted as a set of key-value-pairs where the property names /// are keys, and property values are the values, and copied into the dictionary. Only public /// instance non-index properties are considered. /// public RouteValueDictionary(object obj) : this() { if (obj != null) { var type = obj.GetType(); var allProperties = type.GetRuntimeProperties(); // This is done to support 'new' properties that hide a property on a base class var orderedByDeclaringType = allProperties.OrderBy(p => p.DeclaringType == type ? 0 : 1); foreach (var property in orderedByDeclaringType) { if (property.GetMethod != null && property.GetMethod.IsPublic && !property.GetMethod.IsStatic && property.GetIndexParameters().Length == 0) { var value = property.GetValue(obj); if (ContainsKey(property.Name) && property.DeclaringType != type) { // This is a hidden property, ignore it. } else { Add(property.Name, value); } } } } } /// public object this[[NotNull] string key] { get { object value; _dictionary.TryGetValue(key, out value); return value; } set { _dictionary[key] = value; } } /// /// Gets the comparer for this dictionary. /// /// /// This will always be a reference to /// public IEqualityComparer Comparer { get { return _dictionary.Comparer; } } /// public int Count { get { return _dictionary.Count; } } /// bool ICollection>.IsReadOnly { get { return ((ICollection>)_dictionary).IsReadOnly; } } /// public Dictionary.KeyCollection Keys { get { return _dictionary.Keys; } } /// ICollection IDictionary.Keys { get { return _dictionary.Keys; } } /// public Dictionary.ValueCollection Values { get { return _dictionary.Values; } } /// ICollection IDictionary.Values { get { return _dictionary.Values; } } /// void ICollection>.Add(KeyValuePair item) { ((ICollection>)_dictionary).Add(item); } /// public void Add([NotNull] string key, object value) { _dictionary.Add(key, value); } /// public void Clear() { _dictionary.Clear(); } /// bool ICollection>.Contains(KeyValuePair item) { return ((ICollection>)_dictionary).Contains(item); } /// public bool ContainsKey([NotNull] string key) { return _dictionary.ContainsKey(key); } /// void ICollection>.CopyTo( [NotNull] KeyValuePair[] array, int arrayIndex) { ((ICollection>)_dictionary).CopyTo(array, arrayIndex); } /// public Dictionary.Enumerator GetEnumerator() { return _dictionary.GetEnumerator(); } /// IEnumerator> IEnumerable>.GetEnumerator() { return _dictionary.GetEnumerator(); } /// IEnumerator IEnumerable.GetEnumerator() { return _dictionary.GetEnumerator(); } /// bool ICollection>.Remove(KeyValuePair item) { return ((ICollection>)_dictionary).Remove(item); } /// public bool Remove([NotNull] string key) { return _dictionary.Remove(key); } /// public bool TryGetValue([NotNull] string key, out object value) { return _dictionary.TryGetValue(key, out value); } } }