From d652b868521e017967586402a016f3e5618ee53b Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Thu, 21 Sep 2017 09:19:10 -0700 Subject: [PATCH] Split RVD in twain --- .../DispatcherValueCollection.cs | 790 ++++++++++++++++++ ....AspNetCore.Dispatcher.Abstractions.csproj | 1 + .../Properties/AssemblyInfo.cs | 6 + .../Properties/Resources.Designer.cs | 58 ++ .../Resources.resx | 126 +++ ...oft.AspNetCore.Routing.Abstractions.csproj | 5 +- .../Properties/Resources.Designer.cs | 28 - .../Resources.resx | 6 - .../RouteValueDictionary.cs | 762 +---------------- .../DispatcherAbstractionsTest.cs | 16 - .../DispatcherValueCollectionTest.cs} | 366 ++++---- 11 files changed, 1184 insertions(+), 980 deletions(-) create mode 100644 src/Microsoft.AspNetCore.Dispatcher.Abstractions/DispatcherValueCollection.cs create mode 100644 src/Microsoft.AspNetCore.Dispatcher.Abstractions/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.AspNetCore.Dispatcher.Abstractions/Properties/Resources.Designer.cs create mode 100644 src/Microsoft.AspNetCore.Dispatcher.Abstractions/Resources.resx delete mode 100644 test/Microsoft.AspNetCore.Dispatcher.Abstractions.Test/DispatcherAbstractionsTest.cs rename test/{Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/RouteValueDictionaryTests.cs => Microsoft.AspNetCore.Dispatcher.Abstractions.Test/DispatcherValueCollectionTest.cs} (72%) diff --git a/src/Microsoft.AspNetCore.Dispatcher.Abstractions/DispatcherValueCollection.cs b/src/Microsoft.AspNetCore.Dispatcher.Abstractions/DispatcherValueCollection.cs new file mode 100644 index 0000000000..07fac7420f --- /dev/null +++ b/src/Microsoft.AspNetCore.Dispatcher.Abstractions/DispatcherValueCollection.cs @@ -0,0 +1,790 @@ +// Copyright (c) .NET Foundation. 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.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using Microsoft.AspNetCore.Dispatcher.Abstractions; +using Microsoft.Extensions.Internal; + +namespace Microsoft.AspNetCore.Dispatcher +{ + /// + /// An type for dispatcher values. + /// + public class DispatcherValueCollection : IDictionary, IReadOnlyDictionary + { + internal Storage _storage; + + /// + /// Creates an empty . + /// + public DispatcherValueCollection() + { + _storage = EmptyStorage.Instance; + } + + /// + /// Creates a initialized with the specified . + /// + /// An object to initialize the dictionary. The value can be of type + /// or + /// or an object with public properties as key-value pairs. + /// + /// + /// If the value is a dictionary or other of , + /// then its entries are copied. Otherwise the object 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 DispatcherValueCollection(object values) + { + var dictionary = values as DispatcherValueCollection; + if (dictionary != null) + { + var listStorage = dictionary._storage as ListStorage; + if (listStorage != null) + { + _storage = new ListStorage(listStorage); + return; + } + + var propertyStorage = dictionary._storage as PropertyStorage; + if (propertyStorage != null) + { + // PropertyStorage is immutable so we can just copy it. + _storage = dictionary._storage; + return; + } + + // If we get here, it's an EmptyStorage. + _storage = EmptyStorage.Instance; + return; + } + + var keyValueEnumerable = values as IEnumerable>; + if (keyValueEnumerable != null) + { + var listStorage = new ListStorage(); + _storage = listStorage; + foreach (var kvp in keyValueEnumerable) + { + if (listStorage.ContainsKey(kvp.Key)) + { + var message = Resources.FormatDispatcherValueCollection_DuplicateKey(kvp.Key, nameof(DispatcherValueCollection)); + throw new ArgumentException(message, nameof(values)); + } + + listStorage.Add(kvp); + } + + return; + } + + var stringValueEnumerable = values as IEnumerable>; + if (stringValueEnumerable != null) + { + var listStorage = new ListStorage(); + _storage = listStorage; + foreach (var kvp in stringValueEnumerable) + { + if (listStorage.ContainsKey(kvp.Key)) + { + var message = Resources.FormatDispatcherValueCollection_DuplicateKey(kvp.Key, nameof(DispatcherValueCollection)); + throw new ArgumentException(message, nameof(values)); + } + + listStorage.Add(new KeyValuePair(kvp.Key, kvp.Value)); + } + + return; + } + + if (values != null) + { + _storage = new PropertyStorage(values); + return; + } + + _storage = EmptyStorage.Instance; + } + + /// + public object this[string key] + { + get + { + if (string.IsNullOrEmpty(key)) + { + throw new ArgumentNullException(nameof(key)); + } + + object value; + TryGetValue(key, out value); + return value; + } + + set + { + if (string.IsNullOrEmpty(key)) + { + throw new ArgumentNullException(nameof(key)); + } + + if (!_storage.TrySetValue(key, value)) + { + Upgrade(); + _storage.TrySetValue(key, value); + } + } + } + + /// + /// Gets the comparer for this dictionary. + /// + /// + /// This will always be a reference to + /// + public IEqualityComparer Comparer => StringComparer.OrdinalIgnoreCase; + + /// + public int Count => _storage.Count; + + /// + bool ICollection>.IsReadOnly => false; + + /// + public ICollection Keys + { + get + { + Upgrade(); + + var list = (ListStorage)_storage; + var keys = new string[list.Count]; + for (var i = 0; i < keys.Length; i++) + { + keys[i] = list[i].Key; + } + + return keys; + } + } + + IEnumerable IReadOnlyDictionary.Keys + { + get + { + return Keys; + } + } + + /// + public ICollection Values + { + get + { + Upgrade(); + + var list = (ListStorage)_storage; + var values = new object[list.Count]; + for (var i = 0; i < values.Length; i++) + { + values[i] = list[i].Value; + } + + return values; + } + } + + IEnumerable IReadOnlyDictionary.Values + { + get + { + return Values; + } + } + + /// + void ICollection>.Add(KeyValuePair item) + { + Add(item.Key, item.Value); + } + + /// + public void Add(string key, object value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + Upgrade(); + + var list = (ListStorage)_storage; + for (var i = 0; i < list.Count; i++) + { + if (string.Equals(list[i].Key, key, StringComparison.OrdinalIgnoreCase)) + { + var message = Resources.FormatDispatcherValueCollection_DuplicateKey(key, nameof(DispatcherValueCollection)); + throw new ArgumentException(message, nameof(key)); + } + } + + list.Add(new KeyValuePair(key, value)); + } + + /// + public void Clear() + { + if (_storage.Count == 0) + { + return; + } + + Upgrade(); + + var list = (ListStorage)_storage; + list.Clear(); + } + + /// + bool ICollection>.Contains(KeyValuePair item) + { + if (_storage.Count == 0) + { + return false; + } + + Upgrade(); + + var list = (ListStorage)_storage; + for (var i = 0; i < list.Count; i++) + { + if (string.Equals(list[i].Key, item.Key, StringComparison.OrdinalIgnoreCase)) + { + return EqualityComparer.Default.Equals(list[i].Value, item.Value); + } + } + + return false; + } + + /// + public bool ContainsKey(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _storage.ContainsKey(key); + } + + /// + void ICollection>.CopyTo( + KeyValuePair[] array, + int arrayIndex) + { + if (array == null) + { + throw new ArgumentNullException(nameof(array)); + } + + if (arrayIndex < 0 || arrayIndex > array.Length || array.Length - arrayIndex < this.Count) + { + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); + } + + if (_storage.Count == 0) + { + return; + } + + Upgrade(); + + var list = (ListStorage)_storage; + list.CopyTo(array, arrayIndex); + } + + /// + public Enumerator GetEnumerator() + { + return new Enumerator(this); + } + + /// + IEnumerator> IEnumerable>.GetEnumerator() + { + return GetEnumerator(); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + bool ICollection>.Remove(KeyValuePair item) + { + if (_storage.Count == 0) + { + return false; + } + + Upgrade(); + + var list = (ListStorage)_storage; + for (var i = 0; i < list.Count; i++) + { + if (string.Equals(list[i].Key, item.Key, StringComparison.OrdinalIgnoreCase) && + EqualityComparer.Default.Equals(list[i].Value, item.Value)) + { + list.RemoveAt(i); + return true; + } + } + + return false; + } + + /// + public bool Remove(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (_storage.Count == 0) + { + return false; + } + + Upgrade(); + + var list = (ListStorage)_storage; + for (var i = 0; i < list.Count; i++) + { + if (string.Equals(list[i].Key, key, StringComparison.OrdinalIgnoreCase)) + { + list.RemoveAt(i); + return true; + } + } + + return false; + } + + /// + public bool TryGetValue(string key, out object value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + return _storage.TryGetValue(key, out value); + } + + private void Upgrade() + { + _storage.Upgrade(ref _storage); + } + + public struct Enumerator : IEnumerator> + { + private readonly Storage _storage; + private int _index; + + public Enumerator(DispatcherValueCollection collection) + { + if (collection == null) + { + throw new ArgumentNullException(); + } + + _storage = collection._storage; + + Current = default(KeyValuePair); + _index = -1; + } + + public KeyValuePair Current { get; private set; } + + object IEnumerator.Current => Current; + + public void Dispose() + { + } + + public bool MoveNext() + { + if (++_index < _storage.Count) + { + Current = _storage[_index]; + return true; + } + + Current = default(KeyValuePair); + return false; + } + + public void Reset() + { + Current = default(KeyValuePair); + _index = -1; + } + } + + // Storage and its subclasses are internal for testing. + internal abstract class Storage + { + public abstract int Count { get; } + + public abstract KeyValuePair this[int index] { get; set; } + + public abstract void Upgrade(ref Storage storage); + + public abstract bool TryGetValue(string key, out object value); + + public abstract bool ContainsKey(string key); + + public abstract bool TrySetValue(string key, object value); + } + + internal class ListStorage : Storage + { + private KeyValuePair[] _items; + private int _count; + + private static readonly KeyValuePair[] _emptyArray = new KeyValuePair[0]; + + public ListStorage() + { + _items = _emptyArray; + } + + public ListStorage(int capacity) + { + if (capacity == 0) + { + _items = _emptyArray; + } + else + { + _items = new KeyValuePair[capacity]; + } + } + + public ListStorage(ListStorage other) + { + if (other.Count == 0) + { + _items = _emptyArray; + } + else + { + _items = new KeyValuePair[other.Count]; + for (var i = 0; i < other.Count; i++) + { + this.Add(other[i]); + } + } + } + + public int Capacity => _items.Length; + + public override int Count => _count; + + public override KeyValuePair this[int index] + { + get + { + if (index < 0 || index >= _count) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + return _items[index]; + } + set + { + if (index < 0 || index >= _count) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + _items[index] = value; + } + } + + public void Add(KeyValuePair item) + { + if (_count == _items.Length) + { + EnsureCapacity(_count + 1); + } + + _items[_count++] = item; + } + + public void RemoveAt(int index) + { + _count--; + + for (var i = index; i < _count; i++) + { + _items[i] = _items[i + 1]; + } + + _items[_count] = default(KeyValuePair); + } + + public void Clear() + { + for (var i = 0; i < _count; i++) + { + _items[i] = default(KeyValuePair); + } + + _count = 0; + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + for (var i = 0; i < _count; i++) + { + array[arrayIndex++] = _items[i]; + } + } + + public override bool ContainsKey(string key) + { + for (var i = 0; i < Count; i++) + { + var kvp = _items[i]; + if (string.Equals(key, kvp.Key, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } + + public override bool TrySetValue(string key, object value) + { + for (var i = 0; i < Count; i++) + { + var kvp = _items[i]; + if (string.Equals(key, kvp.Key, StringComparison.OrdinalIgnoreCase)) + { + _items[i] = new KeyValuePair(key, value); + return true; + } + } + + Add(new KeyValuePair(key, value)); + return true; + } + + public override bool TryGetValue(string key, out object value) + { + for (var i = 0; i < Count; i++) + { + var kvp = _items[i]; + if (string.Equals(key, kvp.Key, StringComparison.OrdinalIgnoreCase)) + { + value = kvp.Value; + return true; + } + } + + value = null; + return false; + } + + public override void Upgrade(ref Storage storage) + { + // Do nothing. + } + + private void EnsureCapacity(int min) + { + var newLength = _items.Length == 0 ? 4 : _items.Length * 2; + var newItems = new KeyValuePair[newLength]; + for (var i = 0; i < _count; i++) + { + newItems[i] = _items[i]; + } + + _items = newItems; + } + } + + internal class PropertyStorage : Storage + { + private static readonly PropertyCache _propertyCache = new PropertyCache(); + + internal readonly object _value; + internal readonly PropertyHelper[] _properties; + + public PropertyStorage(object value) + { + Debug.Assert(value != null); + _value = value; + + // Cache the properties so we can know if we've already validated them for duplicates. + var type = _value.GetType(); + if (!_propertyCache.TryGetValue(type, out _properties)) + { + _properties = PropertyHelper.GetVisibleProperties(type); + ValidatePropertyNames(type, _properties); + _propertyCache.TryAdd(type, _properties); + } + } + + public PropertyStorage(PropertyStorage propertyStorage) + { + _value = propertyStorage._value; + _properties = propertyStorage._properties; + } + + public override int Count => _properties.Length; + + public override KeyValuePair this[int index] + { + get + { + var property = _properties[index]; + return new KeyValuePair(property.Name, property.GetValue(_value)); + } + set + { + // PropertyStorage never sets a value. + throw new NotImplementedException(); + } + } + + public override bool TryGetValue(string key, out object value) + { + for (var i = 0; i < _properties.Length; i++) + { + var property = _properties[i]; + if (string.Equals(key, property.Name, StringComparison.OrdinalIgnoreCase)) + { + value = property.GetValue(_value); + return true; + } + } + + value = null; + return false; + } + + public override bool ContainsKey(string key) + { + for (var i = 0; i < _properties.Length; i++) + { + var property = _properties[i]; + if (string.Equals(key, property.Name, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } + + public override bool TrySetValue(string key, object value) + { + // PropertyStorage never sets a value. + return false; + } + + public override void Upgrade(ref Storage storage) + { + storage = new ListStorage(Count); + for (var i = 0; i < _properties.Length; i++) + { + var property = _properties[i]; + storage.TrySetValue(property.Name, property.GetValue(_value)); + } + } + + private static void ValidatePropertyNames(Type type, PropertyHelper[] properties) + { + var names = new Dictionary(StringComparer.OrdinalIgnoreCase); + for (var i = 0; i < properties.Length; i++) + { + var property = properties[i]; + + PropertyHelper duplicate; + if (names.TryGetValue(property.Name, out duplicate)) + { + var message = Resources.FormatDispatcherValueCollection_DuplicatePropertyName( + type.FullName, + property.Name, + duplicate.Name, + nameof(DispatcherValueCollection)); + throw new InvalidOperationException(message); + } + + names.Add(property.Name, property); + } + } + } + + internal class EmptyStorage : Storage + { + public static readonly EmptyStorage Instance = new EmptyStorage(); + + private EmptyStorage() + { + } + + public override int Count => 0; + + public override KeyValuePair this[int index] + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + + public override bool ContainsKey(string key) + { + return false; + } + + public override bool TryGetValue(string key, out object value) + { + value = null; + return false; + } + + public override bool TrySetValue(string key, object value) + { + return false; + } + + public override void Upgrade(ref Storage storage) + { + storage = new ListStorage(); + } + } + + private class PropertyCache : ConcurrentDictionary + { + } + } +} diff --git a/src/Microsoft.AspNetCore.Dispatcher.Abstractions/Microsoft.AspNetCore.Dispatcher.Abstractions.csproj b/src/Microsoft.AspNetCore.Dispatcher.Abstractions/Microsoft.AspNetCore.Dispatcher.Abstractions.csproj index 179b35ceb4..721dadb4e4 100644 --- a/src/Microsoft.AspNetCore.Dispatcher.Abstractions/Microsoft.AspNetCore.Dispatcher.Abstractions.csproj +++ b/src/Microsoft.AspNetCore.Dispatcher.Abstractions/Microsoft.AspNetCore.Dispatcher.Abstractions.csproj @@ -9,6 +9,7 @@ + diff --git a/src/Microsoft.AspNetCore.Dispatcher.Abstractions/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.Dispatcher.Abstractions/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..7694000f8e --- /dev/null +++ b/src/Microsoft.AspNetCore.Dispatcher.Abstractions/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Dispatcher.Abstractions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Dispatcher.Abstractions/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Dispatcher.Abstractions/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..7c28389bab --- /dev/null +++ b/src/Microsoft.AspNetCore.Dispatcher.Abstractions/Properties/Resources.Designer.cs @@ -0,0 +1,58 @@ +// +namespace Microsoft.AspNetCore.Dispatcher.Abstractions +{ + using System.Globalization; + using System.Reflection; + using System.Resources; + + internal static class Resources + { + private static readonly ResourceManager _resourceManager + = new ResourceManager("Microsoft.AspNetCore.Dispatcher.Abstractions.Resources", typeof(Resources).GetTypeInfo().Assembly); + + /// + /// An element with the key '{0}' already exists in the {1}. + /// + internal static string DispatcherValueCollection_DuplicateKey + { + get => GetString("DispatcherValueCollection_DuplicateKey"); + } + + /// + /// An element with the key '{0}' already exists in the {1}. + /// + internal static string FormatDispatcherValueCollection_DuplicateKey(object p0, object p1) + => string.Format(CultureInfo.CurrentCulture, GetString("DispatcherValueCollection_DuplicateKey"), p0, p1); + + /// + /// The type '{0}' defines properties '{1}' and '{2}' which differ only by casing. This is not supported by {3} which uses case-insensitive comparisons. + /// + internal static string DispatcherValueCollection_DuplicatePropertyName + { + get => GetString("DispatcherValueCollection_DuplicatePropertyName"); + } + + /// + /// The type '{0}' defines properties '{1}' and '{2}' which differ only by casing. This is not supported by {3} which uses case-insensitive comparisons. + /// + internal static string FormatDispatcherValueCollection_DuplicatePropertyName(object p0, object p1, object p2, object p3) + => string.Format(CultureInfo.CurrentCulture, GetString("DispatcherValueCollection_DuplicatePropertyName"), p0, p1, p2, p3); + + private static string GetString(string name, params string[] formatterNames) + { + var value = _resourceManager.GetString(name); + + System.Diagnostics.Debug.Assert(value != null); + + if (formatterNames != null) + { + for (var i = 0; i < formatterNames.Length; i++) + { + value = value.Replace("{" + formatterNames[i] + "}", "{" + i + "}"); + } + } + + return value; + } + } +} diff --git a/src/Microsoft.AspNetCore.Dispatcher.Abstractions/Resources.resx b/src/Microsoft.AspNetCore.Dispatcher.Abstractions/Resources.resx new file mode 100644 index 0000000000..642921cc04 --- /dev/null +++ b/src/Microsoft.AspNetCore.Dispatcher.Abstractions/Resources.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + An element with the key '{0}' already exists in the {1}. + + + The type '{0}' defines properties '{1}' and '{2}' which differ only by casing. This is not supported by {3} which uses case-insensitive comparisons. + + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/Microsoft.AspNetCore.Routing.Abstractions.csproj b/src/Microsoft.AspNetCore.Routing.Abstractions/Microsoft.AspNetCore.Routing.Abstractions.csproj index 48fb778687..b768b04801 100644 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/Microsoft.AspNetCore.Routing.Abstractions.csproj +++ b/src/Microsoft.AspNetCore.Routing.Abstractions/Microsoft.AspNetCore.Routing.Abstractions.csproj @@ -13,6 +13,9 @@ Microsoft.AspNetCore.Routing.RouteData - + + + + diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Routing.Abstractions/Properties/Resources.Designer.cs index 8fdf6b8715..2ac5d0972c 100644 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.Routing.Abstractions/Properties/Resources.Designer.cs @@ -10,34 +10,6 @@ namespace Microsoft.AspNetCore.Routing.Abstractions private static readonly ResourceManager _resourceManager = new ResourceManager("Microsoft.AspNetCore.Routing.Abstractions.Resources", typeof(Resources).GetTypeInfo().Assembly); - /// - /// An element with the key '{0}' already exists in the {1}. - /// - internal static string RouteValueDictionary_DuplicateKey - { - get => GetString("RouteValueDictionary_DuplicateKey"); - } - - /// - /// An element with the key '{0}' already exists in the {1}. - /// - internal static string FormatRouteValueDictionary_DuplicateKey(object p0, object p1) - => string.Format(CultureInfo.CurrentCulture, GetString("RouteValueDictionary_DuplicateKey"), p0, p1); - - /// - /// The type '{0}' defines properties '{1}' and '{2}' which differ only by casing. This is not supported by {3} which uses case-insensitive comparisons. - /// - internal static string RouteValueDictionary_DuplicatePropertyName - { - get => GetString("RouteValueDictionary_DuplicatePropertyName"); - } - - /// - /// The type '{0}' defines properties '{1}' and '{2}' which differ only by casing. This is not supported by {3} which uses case-insensitive comparisons. - /// - internal static string FormatRouteValueDictionary_DuplicatePropertyName(object p0, object p1, object p2, object p3) - => string.Format(CultureInfo.CurrentCulture, GetString("RouteValueDictionary_DuplicatePropertyName"), p0, p1, p2, p3); - private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/Resources.resx b/src/Microsoft.AspNetCore.Routing.Abstractions/Resources.resx index 40e651af14..1af7de150c 100644 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/Resources.resx +++ b/src/Microsoft.AspNetCore.Routing.Abstractions/Resources.resx @@ -117,10 +117,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - An element with the key '{0}' already exists in the {1}. - - - The type '{0}' defines properties '{1}' and '{2}' which differ only by casing. This is not supported by {3} which uses case-insensitive comparisons. - \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Routing.Abstractions/RouteValueDictionary.cs b/src/Microsoft.AspNetCore.Routing.Abstractions/RouteValueDictionary.cs index d0bc8e9ecf..cc05d64b6c 100644 --- a/src/Microsoft.AspNetCore.Routing.Abstractions/RouteValueDictionary.cs +++ b/src/Microsoft.AspNetCore.Routing.Abstractions/RouteValueDictionary.cs @@ -3,402 +3,30 @@ using System; using System.Collections; -using System.Collections.Concurrent; using System.Collections.Generic; -using System.Diagnostics; -using Microsoft.AspNetCore.Routing.Abstractions; -using Microsoft.Extensions.Internal; +using Microsoft.AspNetCore.Dispatcher; namespace Microsoft.AspNetCore.Routing { - /// - /// An type for route values. - /// - public class RouteValueDictionary : IDictionary, IReadOnlyDictionary + public class RouteValueDictionary : DispatcherValueCollection { - internal Storage _storage; - - /// - /// Creates an empty . - /// public RouteValueDictionary() + : base() { - _storage = EmptyStorage.Instance; } - /// - /// Creates a initialized with the specified . - /// - /// An object to initialize the dictionary. The value can be of type - /// or - /// or an object with public properties as key-value pairs. - /// - /// - /// If the value is a dictionary or other of , - /// then its entries are copied. Otherwise the object 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 values) + public RouteValueDictionary(object obj) + : base(obj) { - var dictionary = values as RouteValueDictionary; - if (dictionary != null) - { - var listStorage = dictionary._storage as ListStorage; - if (listStorage != null) - { - _storage = new ListStorage(listStorage); - return; - } - - var propertyStorage = dictionary._storage as PropertyStorage; - if (propertyStorage != null) - { - // PropertyStorage is immutable so we can just copy it. - _storage = dictionary._storage; - return; - } - - // If we get here, it's an EmptyStorage. - _storage = EmptyStorage.Instance; - return; - } - - var keyValueEnumerable = values as IEnumerable>; - if (keyValueEnumerable != null) - { - var listStorage = new ListStorage(); - _storage = listStorage; - foreach (var kvp in keyValueEnumerable) - { - if (listStorage.ContainsKey(kvp.Key)) - { - var message = Resources.FormatRouteValueDictionary_DuplicateKey(kvp.Key, nameof(RouteValueDictionary)); - throw new ArgumentException(message, nameof(values)); - } - - listStorage.Add(kvp); - } - - return; - } - - var stringValueEnumerable = values as IEnumerable>; - if (stringValueEnumerable != null) - { - var listStorage = new ListStorage(); - _storage = listStorage; - foreach (var kvp in stringValueEnumerable) - { - if (listStorage.ContainsKey(kvp.Key)) - { - var message = Resources.FormatRouteValueDictionary_DuplicateKey(kvp.Key, nameof(RouteValueDictionary)); - throw new ArgumentException(message, nameof(values)); - } - - listStorage.Add(new KeyValuePair(kvp.Key, kvp.Value)); - } - - return; - } - - if (values != null) - { - _storage = new PropertyStorage(values); - return; - } - - _storage = EmptyStorage.Instance; } - /// - public object this[string key] + // Required to avoid a breaking change in the split of RVD/DVC + public new Enumerator GetEnumerator() => new Enumerator(this); + + // Required to avoid a breaking change in the split of RVD/DVC + public new struct Enumerator : IEnumerator> { - get - { - if (string.IsNullOrEmpty(key)) - { - throw new ArgumentNullException(nameof(key)); - } - - object value; - TryGetValue(key, out value); - return value; - } - - set - { - if (string.IsNullOrEmpty(key)) - { - throw new ArgumentNullException(nameof(key)); - } - - if (!_storage.TrySetValue(key, value)) - { - Upgrade(); - _storage.TrySetValue(key, value); - } - } - } - - /// - /// Gets the comparer for this dictionary. - /// - /// - /// This will always be a reference to - /// - public IEqualityComparer Comparer => StringComparer.OrdinalIgnoreCase; - - /// - public int Count => _storage.Count; - - /// - bool ICollection>.IsReadOnly => false; - - /// - public ICollection Keys - { - get - { - Upgrade(); - - var list = (ListStorage)_storage; - var keys = new string[list.Count]; - for (var i = 0; i < keys.Length; i++) - { - keys[i] = list[i].Key; - } - - return keys; - } - } - - IEnumerable IReadOnlyDictionary.Keys - { - get - { - return Keys; - } - } - - /// - public ICollection Values - { - get - { - Upgrade(); - - var list = (ListStorage)_storage; - var values = new object[list.Count]; - for (var i = 0; i < values.Length; i++) - { - values[i] = list[i].Value; - } - - return values; - } - } - - IEnumerable IReadOnlyDictionary.Values - { - get - { - return Values; - } - } - - /// - void ICollection>.Add(KeyValuePair item) - { - Add(item.Key, item.Value); - } - - /// - public void Add(string key, object value) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - Upgrade(); - - var list = (ListStorage)_storage; - for (var i = 0; i < list.Count; i++) - { - if (string.Equals(list[i].Key, key, StringComparison.OrdinalIgnoreCase)) - { - var message = Resources.FormatRouteValueDictionary_DuplicateKey(key, nameof(RouteValueDictionary)); - throw new ArgumentException(message, nameof(key)); - } - } - - list.Add(new KeyValuePair(key, value)); - } - - /// - public void Clear() - { - if (_storage.Count == 0) - { - return; - } - - Upgrade(); - - var list = (ListStorage)_storage; - list.Clear(); - } - - /// - bool ICollection>.Contains(KeyValuePair item) - { - if (_storage.Count == 0) - { - return false; - } - - Upgrade(); - - var list = (ListStorage)_storage; - for (var i = 0; i < list.Count; i++) - { - if (string.Equals(list[i].Key, item.Key, StringComparison.OrdinalIgnoreCase)) - { - return EqualityComparer.Default.Equals(list[i].Value, item.Value); - } - } - - return false; - } - - /// - public bool ContainsKey(string key) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - return _storage.ContainsKey(key); - } - - /// - void ICollection>.CopyTo( - KeyValuePair[] array, - int arrayIndex) - { - if (array == null) - { - throw new ArgumentNullException(nameof(array)); - } - - if (arrayIndex < 0 || arrayIndex > array.Length || array.Length - arrayIndex < this.Count) - { - throw new ArgumentOutOfRangeException(nameof(arrayIndex)); - } - - if (_storage.Count == 0) - { - return; - } - - Upgrade(); - - var list = (ListStorage)_storage; - list.CopyTo(array, arrayIndex); - } - - /// - public Enumerator GetEnumerator() - { - return new Enumerator(this); - } - - /// - IEnumerator> IEnumerable>.GetEnumerator() - { - return GetEnumerator(); - } - - /// - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - /// - bool ICollection>.Remove(KeyValuePair item) - { - if (_storage.Count == 0) - { - return false; - } - - Upgrade(); - - var list = (ListStorage)_storage; - for (var i = 0; i < list.Count; i++) - { - if (string.Equals(list[i].Key, item.Key, StringComparison.OrdinalIgnoreCase) && - EqualityComparer.Default.Equals(list[i].Value, item.Value)) - { - list.RemoveAt(i); - return true; - } - } - - return false; - } - - /// - public bool Remove(string key) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - if (_storage.Count == 0) - { - return false; - } - - Upgrade(); - - var list = (ListStorage)_storage; - for (var i = 0; i < list.Count; i++) - { - if (string.Equals(list[i].Key, key, StringComparison.OrdinalIgnoreCase)) - { - list.RemoveAt(i); - return true; - } - } - - return false; - } - - /// - public bool TryGetValue(string key, out object value) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - return _storage.TryGetValue(key, out value); - } - - private void Upgrade() - { - _storage.Upgrade(ref _storage); - } - - public struct Enumerator : IEnumerator> - { - private readonly Storage _storage; - private int _index; + private DispatcherValueCollection.Enumerator _inner; public Enumerator(RouteValueDictionary dictionary) { @@ -407,15 +35,12 @@ namespace Microsoft.AspNetCore.Routing throw new ArgumentNullException(); } - _storage = dictionary._storage; - - Current = default(KeyValuePair); - _index = -1; + _inner = ((DispatcherValueCollection)dictionary).GetEnumerator(); } - public KeyValuePair Current { get; private set; } + public KeyValuePair Current => _inner.Current; - object IEnumerator.Current => Current; + object IEnumerator.Current => _inner.Current; public void Dispose() { @@ -423,368 +48,13 @@ namespace Microsoft.AspNetCore.Routing public bool MoveNext() { - if (++_index < _storage.Count) - { - Current = _storage[_index]; - return true; - } - - Current = default(KeyValuePair); - return false; + return _inner.MoveNext(); } public void Reset() { - Current = default(KeyValuePair); - _index = -1; + _inner.Reset(); } } - - // Storage and its subclasses are internal for testing. - internal abstract class Storage - { - public abstract int Count { get; } - - public abstract KeyValuePair this[int index] { get; set; } - - public abstract void Upgrade(ref Storage storage); - - public abstract bool TryGetValue(string key, out object value); - - public abstract bool ContainsKey(string key); - - public abstract bool TrySetValue(string key, object value); - } - - internal class ListStorage : Storage - { - private KeyValuePair[] _items; - private int _count; - - private static readonly KeyValuePair[] _emptyArray = new KeyValuePair[0]; - - public ListStorage() - { - _items = _emptyArray; - } - - public ListStorage(int capacity) - { - if (capacity == 0) - { - _items = _emptyArray; - } - else - { - _items = new KeyValuePair[capacity]; - } - } - - public ListStorage(ListStorage other) - { - if (other.Count == 0) - { - _items = _emptyArray; - } - else - { - _items = new KeyValuePair[other.Count]; - for (var i = 0; i < other.Count; i++) - { - this.Add(other[i]); - } - } - } - - public int Capacity => _items.Length; - - public override int Count => _count; - - public override KeyValuePair this[int index] - { - get - { - if (index < 0 || index >= _count) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - - return _items[index]; - } - set - { - if (index < 0 || index >= _count) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - - _items[index] = value; - } - } - - public void Add(KeyValuePair item) - { - if (_count == _items.Length) - { - EnsureCapacity(_count + 1); - } - - _items[_count++] = item; - } - - public void RemoveAt(int index) - { - _count--; - - for (var i = index; i < _count; i++) - { - _items[i] = _items[i + 1]; - } - - _items[_count] = default(KeyValuePair); - } - - public void Clear() - { - for (var i = 0; i < _count; i++) - { - _items[i] = default(KeyValuePair); - } - - _count = 0; - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - for (var i = 0; i < _count; i++) - { - array[arrayIndex++] = _items[i]; - } - } - - public override bool ContainsKey(string key) - { - for (var i = 0; i < Count; i++) - { - var kvp = _items[i]; - if (string.Equals(key, kvp.Key, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - } - - return false; - } - - public override bool TrySetValue(string key, object value) - { - for (var i = 0; i < Count; i++) - { - var kvp = _items[i]; - if (string.Equals(key, kvp.Key, StringComparison.OrdinalIgnoreCase)) - { - _items[i] = new KeyValuePair(key, value); - return true; - } - } - - Add(new KeyValuePair(key, value)); - return true; - } - - public override bool TryGetValue(string key, out object value) - { - for (var i = 0; i < Count; i++) - { - var kvp = _items[i]; - if (string.Equals(key, kvp.Key, StringComparison.OrdinalIgnoreCase)) - { - value = kvp.Value; - return true; - } - } - - value = null; - return false; - } - - public override void Upgrade(ref Storage storage) - { - // Do nothing. - } - - private void EnsureCapacity(int min) - { - var newLength = _items.Length == 0 ? 4 : _items.Length * 2; - var newItems = new KeyValuePair[newLength]; - for (var i = 0; i < _count; i++) - { - newItems[i] = _items[i]; - } - - _items = newItems; - } - } - - internal class PropertyStorage : Storage - { - private static readonly PropertyCache _propertyCache = new PropertyCache(); - - internal readonly object _value; - internal readonly PropertyHelper[] _properties; - - public PropertyStorage(object value) - { - Debug.Assert(value != null); - _value = value; - - // Cache the properties so we can know if we've already validated them for duplicates. - var type = _value.GetType(); - if (!_propertyCache.TryGetValue(type, out _properties)) - { - _properties = PropertyHelper.GetVisibleProperties(type); - ValidatePropertyNames(type, _properties); - _propertyCache.TryAdd(type, _properties); - } - } - - public PropertyStorage(PropertyStorage propertyStorage) - { - _value = propertyStorage._value; - _properties = propertyStorage._properties; - } - - public override int Count => _properties.Length; - - public override KeyValuePair this[int index] - { - get - { - var property = _properties[index]; - return new KeyValuePair(property.Name, property.GetValue(_value)); - } - set - { - // PropertyStorage never sets a value. - throw new NotImplementedException(); - } - } - - public override bool TryGetValue(string key, out object value) - { - for (var i = 0; i < _properties.Length; i++) - { - var property = _properties[i]; - if (string.Equals(key, property.Name, StringComparison.OrdinalIgnoreCase)) - { - value = property.GetValue(_value); - return true; - } - } - - value = null; - return false; - } - - public override bool ContainsKey(string key) - { - for (var i = 0; i < _properties.Length; i++) - { - var property = _properties[i]; - if (string.Equals(key, property.Name, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - } - - return false; - } - - public override bool TrySetValue(string key, object value) - { - // PropertyStorage never sets a value. - return false; - } - - public override void Upgrade(ref Storage storage) - { - storage = new ListStorage(Count); - for (var i = 0; i < _properties.Length; i++) - { - var property = _properties[i]; - storage.TrySetValue(property.Name, property.GetValue(_value)); - } - } - - private static void ValidatePropertyNames(Type type, PropertyHelper[] properties) - { - var names = new Dictionary(StringComparer.OrdinalIgnoreCase); - for (var i = 0; i < properties.Length; i++) - { - var property = properties[i]; - - PropertyHelper duplicate; - if (names.TryGetValue(property.Name, out duplicate)) - { - var message = Resources.FormatRouteValueDictionary_DuplicatePropertyName( - type.FullName, - property.Name, - duplicate.Name, - nameof(RouteValueDictionary)); - throw new InvalidOperationException(message); - } - - names.Add(property.Name, property); - } - } - } - - internal class EmptyStorage : Storage - { - public static readonly EmptyStorage Instance = new EmptyStorage(); - - private EmptyStorage() - { - } - - public override int Count => 0; - - public override KeyValuePair this[int index] - { - get - { - throw new NotImplementedException(); - } - set - { - throw new NotImplementedException(); - } - } - - public override bool ContainsKey(string key) - { - return false; - } - - public override bool TryGetValue(string key, out object value) - { - value = null; - return false; - } - - public override bool TrySetValue(string key, object value) - { - return false; - } - - public override void Upgrade(ref Storage storage) - { - storage = new ListStorage(); - } - } - - private class PropertyCache : ConcurrentDictionary - { - } } } diff --git a/test/Microsoft.AspNetCore.Dispatcher.Abstractions.Test/DispatcherAbstractionsTest.cs b/test/Microsoft.AspNetCore.Dispatcher.Abstractions.Test/DispatcherAbstractionsTest.cs deleted file mode 100644 index 8d76aa553c..0000000000 --- a/test/Microsoft.AspNetCore.Dispatcher.Abstractions.Test/DispatcherAbstractionsTest.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using Xunit; - -namespace Microsoft.AspNetCore.Dispatcher.Abstractions.Test -{ - public class DispatcherAbstractionsTest - { - [Fact] - public void Test() - { - - } - } -} diff --git a/test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/RouteValueDictionaryTests.cs b/test/Microsoft.AspNetCore.Dispatcher.Abstractions.Test/DispatcherValueCollectionTest.cs similarity index 72% rename from test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/RouteValueDictionaryTests.cs rename to test/Microsoft.AspNetCore.Dispatcher.Abstractions.Test/DispatcherValueCollectionTest.cs index 764f773e16..ad62178b3c 100644 --- a/test/Microsoft.AspNetCore.Mvc.Routing.Abstractions.Tests/RouteValueDictionaryTests.cs +++ b/test/Microsoft.AspNetCore.Dispatcher.Abstractions.Test/DispatcherValueCollectionTest.cs @@ -7,20 +7,20 @@ using System.Linq; using Microsoft.AspNetCore.Testing; using Xunit; -namespace Microsoft.AspNetCore.Routing.Tests +namespace Microsoft.AspNetCore.Dispatcher { - public class RouteValueDictionaryTests + public class DispatcherValueCollectionTest { [Fact] public void DefaultCtor_UsesEmptyStorage() { // Arrange // Act - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); // Assert Assert.Empty(dict); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] @@ -28,64 +28,64 @@ namespace Microsoft.AspNetCore.Routing.Tests { // Arrange // Act - var dict = new RouteValueDictionary(null); + var dict = new DispatcherValueCollection(null); // Assert Assert.Empty(dict); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] - public void CreateFromRouteValueDictionary_WithListStorage_CopiesStorage() + public void CreateFromDispatcherValueCollection_WithListStorage_CopiesStorage() { // Arrange - var other = new RouteValueDictionary() + var other = new DispatcherValueCollection() { { "1", 1 } }; // Act - var dict = new RouteValueDictionary(other); + var dict = new DispatcherValueCollection(other); // Assert Assert.Equal(other, dict); - var storage = Assert.IsType(dict._storage); - var otherStorage = Assert.IsType(other._storage); + var storage = Assert.IsType(dict._storage); + var otherStorage = Assert.IsType(other._storage); Assert.NotSame(otherStorage, storage); } [Fact] - public void CreateFromRouteValueDictionary_WithPropertyStorage_CopiesStorage() + public void CreateFromDispatcherValueCollection_WithPropertyStorage_CopiesStorage() { // Arrange - var other = new RouteValueDictionary(new { key = "value" }); + var other = new DispatcherValueCollection(new { key = "value" }); // Act - var dict = new RouteValueDictionary(other); + var dict = new DispatcherValueCollection(other); // Assert Assert.Equal(other, dict); - var storage = Assert.IsType(dict._storage); - var otherStorage = Assert.IsType(other._storage); + var storage = Assert.IsType(dict._storage); + var otherStorage = Assert.IsType(other._storage); Assert.Same(otherStorage, storage); } [Fact] - public void CreateFromRouteValueDictionary_WithEmptyStorage_SharedInstance() + public void CreateFromDispatcherValueCollection_WithEmptyStorage_SharedInstance() { // Arrange - var other = new RouteValueDictionary(); + var other = new DispatcherValueCollection(); // Act - var dict = new RouteValueDictionary(other); + var dict = new DispatcherValueCollection(other); // Assert Assert.Equal(other, dict); - var storage = Assert.IsType(dict._storage); - var otherStorage = Assert.IsType(other._storage); + var storage = Assert.IsType(dict._storage); + var otherStorage = Assert.IsType(other._storage); Assert.Same(otherStorage, storage); } @@ -132,10 +132,10 @@ namespace Microsoft.AspNetCore.Routing.Tests public void CreateFromIEnumerableKeyValuePair_CopiesValues(object values) { // Arrange & Act - var dict = new RouteValueDictionary(values); + var dict = new DispatcherValueCollection(values); // Assert - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); Assert.Collection( dict.OrderBy(kvp => kvp.Key), kvp => @@ -154,10 +154,10 @@ namespace Microsoft.AspNetCore.Routing.Tests public void CreateFromIEnumerableStringValuePair_CopiesValues(object values) { // Arrange & Act - var dict = new RouteValueDictionary(values); + var dict = new DispatcherValueCollection(values); // Assert - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); Assert.Collection( dict.OrderBy(kvp => kvp.Key), kvp => { Assert.Equal("First Name", kvp.Key); Assert.Equal("James", kvp.Value); }, @@ -177,9 +177,9 @@ namespace Microsoft.AspNetCore.Routing.Tests // Act & Assert ExceptionAssert.ThrowsArgument( - () => new RouteValueDictionary(values), + () => new DispatcherValueCollection(values), "values", - $"An element with the key 'Name' already exists in the {nameof(RouteValueDictionary)}."); + $"An element with the key 'Name' already exists in the {nameof(DispatcherValueCollection)}."); } [Fact] @@ -194,9 +194,9 @@ namespace Microsoft.AspNetCore.Routing.Tests // Act & Assert ExceptionAssert.ThrowsArgument( - () => new RouteValueDictionary(values), + () => new DispatcherValueCollection(values), "values", - $"An element with the key 'Name' already exists in the {nameof(RouteValueDictionary)}."); + $"An element with the key 'Name' already exists in the {nameof(DispatcherValueCollection)}."); } [Fact] @@ -206,10 +206,10 @@ namespace Microsoft.AspNetCore.Routing.Tests var obj = new { cool = "beans", awesome = 123 }; // Act - var dict = new RouteValueDictionary(obj); + var dict = new DispatcherValueCollection(obj); // Assert - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); Assert.Collection( dict.OrderBy(kvp => kvp.Key), kvp => { Assert.Equal("awesome", kvp.Key); Assert.Equal(123, kvp.Value); }, @@ -223,10 +223,10 @@ namespace Microsoft.AspNetCore.Routing.Tests var obj = new RegularType() { CoolnessFactor = 73 }; // Act - var dict = new RouteValueDictionary(obj); + var dict = new DispatcherValueCollection(obj); // Assert - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); Assert.Collection( dict.OrderBy(kvp => kvp.Key), kvp => @@ -249,10 +249,10 @@ namespace Microsoft.AspNetCore.Routing.Tests var obj = new Visibility() { IsPublic = true, ItsInternalDealWithIt = 5 }; // Act - var dict = new RouteValueDictionary(obj); + var dict = new DispatcherValueCollection(obj); // Assert - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); Assert.Collection( dict.OrderBy(kvp => kvp.Key), kvp => @@ -270,10 +270,10 @@ namespace Microsoft.AspNetCore.Routing.Tests var obj = new StaticProperty(); // Act - var dict = new RouteValueDictionary(obj); + var dict = new DispatcherValueCollection(obj); // Assert - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); Assert.Empty(dict); } @@ -284,10 +284,10 @@ namespace Microsoft.AspNetCore.Routing.Tests var obj = new SetterOnly() { CoolSetOnly = false }; // Act - var dict = new RouteValueDictionary(obj); + var dict = new DispatcherValueCollection(obj); // Assert - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); Assert.Empty(dict); } @@ -298,10 +298,10 @@ namespace Microsoft.AspNetCore.Routing.Tests var obj = new Derived() { TotallySweetProperty = true, DerivedProperty = false }; // Act - var dict = new RouteValueDictionary(obj); + var dict = new DispatcherValueCollection(obj); // Assert - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); Assert.Collection( dict.OrderBy(kvp => kvp.Key), kvp => @@ -325,10 +325,10 @@ namespace Microsoft.AspNetCore.Routing.Tests var obj = new DerivedHiddenProperty() { DerivedProperty = 5 }; // Act - var dict = new RouteValueDictionary(obj); + var dict = new DispatcherValueCollection(obj); // Assert - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); Assert.Collection( dict.OrderBy(kvp => kvp.Key), kvp => { Assert.Equal("DerivedProperty", kvp.Key); Assert.Equal(5, kvp.Value); }); @@ -341,10 +341,10 @@ namespace Microsoft.AspNetCore.Routing.Tests var obj = new IndexerProperty(); // Act - var dict = new RouteValueDictionary(obj); + var dict = new DispatcherValueCollection(obj); // Assert - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); Assert.Empty(dict); } @@ -356,13 +356,13 @@ namespace Microsoft.AspNetCore.Routing.Tests var message = $"The type '{obj.GetType().FullName}' defines properties 'controller' and 'Controller' which differ " + - $"only by casing. This is not supported by {nameof(RouteValueDictionary)} which uses " + + $"only by casing. This is not supported by {nameof(DispatcherValueCollection)} which uses " + $"case-insensitive comparisons."; // Act & Assert var exception = Assert.Throws(() => { - var dictionary = new RouteValueDictionary(obj); + var dictionary = new DispatcherValueCollection(obj); }); // Ignoring case to make sure we're not testing reflection's ordering. @@ -375,7 +375,7 @@ namespace Microsoft.AspNetCore.Routing.Tests { // Arrange // Act - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); // Assert Assert.Same(StringComparer.OrdinalIgnoreCase, dict.Comparer); @@ -386,7 +386,7 @@ namespace Microsoft.AspNetCore.Routing.Tests public void IsReadOnly_False() { // Arrange - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); // Act var result = ((ICollection>)dict).IsReadOnly; @@ -399,63 +399,63 @@ namespace Microsoft.AspNetCore.Routing.Tests public void IndexGet_EmptyStorage_ReturnsNull() { // Arrange - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); // Act var value = dict["key"]; // Assert Assert.Null(value); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void IndexGet_PropertyStorage_NoMatch_ReturnsNull() { // Arrange - var dict = new RouteValueDictionary(new { age = 30 }); + var dict = new DispatcherValueCollection(new { age = 30 }); // Act var value = dict["key"]; // Assert Assert.Null(value); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void IndexGet_PropertyStorage_Match_ReturnsValue() { // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); + var dict = new DispatcherValueCollection(new { key = "value" }); // Act var value = dict["key"]; // Assert Assert.Equal("value", value); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void IndexGet_PropertyStorage_MatchIgnoreCase_ReturnsValue() { // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); + var dict = new DispatcherValueCollection(new { key = "value" }); // Act var value = dict["kEy"]; // Assert Assert.Equal("value", value); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void IndexGet_ListStorage_NoMatch_ReturnsNull() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "age", 30 }, }; @@ -465,14 +465,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.Null(value); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void IndexGet_ListStorage_Match_ReturnsValue() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -482,14 +482,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.Equal("value", value); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void IndexGet_ListStorage_MatchIgnoreCase_ReturnsValue() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -499,28 +499,28 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.Equal("value", value); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void IndexSet_EmptyStorage_UpgradesToList() { // Arrange - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); // Act dict["key"] = "value"; // Assert Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void IndexSet_PropertyStorage_NoMatch_AddsValue() { // Arrange - var dict = new RouteValueDictionary(new { age = 30 }); + var dict = new DispatcherValueCollection(new { age = 30 }); // Act dict["key"] = "value"; @@ -530,42 +530,42 @@ namespace Microsoft.AspNetCore.Routing.Tests dict.OrderBy(kvp => kvp.Key), kvp => { Assert.Equal("age", kvp.Key); Assert.Equal(30, kvp.Value); }, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void IndexSet_PropertyStorage_Match_SetsValue() { // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); + var dict = new DispatcherValueCollection(new { key = "value" }); // Act dict["key"] = "value"; // Assert Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void IndexSet_PropertyStorage_MatchIgnoreCase_SetsValue() { // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); + var dict = new DispatcherValueCollection(new { key = "value" }); // Act dict["kEy"] = "value"; // Assert Assert.Collection(dict, kvp => { Assert.Equal("kEy", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void IndexSet_ListStorage_NoMatch_AddsValue() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "age", 30 }, }; @@ -578,14 +578,14 @@ namespace Microsoft.AspNetCore.Routing.Tests dict.OrderBy(kvp => kvp.Key), kvp => { Assert.Equal("age", kvp.Key); Assert.Equal(30, kvp.Value); }, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void IndexSet_ListStorage_Match_SetsValue() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -595,14 +595,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void IndexSet_ListStorage_MatchIgnoreCase_SetsValue() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -612,42 +612,42 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Count_EmptyStorage() { // Arrange - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); // Act var count = dict.Count; // Assert Assert.Equal(0, count); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Count_PropertyStorage() { // Arrange - var dict = new RouteValueDictionary(new { key = "value", }); + var dict = new DispatcherValueCollection(new { key = "value", }); // Act var count = dict.Count; // Assert Assert.Equal(1, count); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Count_ListStorage() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -657,42 +657,42 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.Equal(1, count); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Keys_EmptyStorage() { // Arrange - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); // Act var keys = dict.Keys; // Assert Assert.Empty(keys); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Keys_PropertyStorage() { // Arrange - var dict = new RouteValueDictionary(new { key = "value", }); + var dict = new DispatcherValueCollection(new { key = "value", }); // Act var keys = dict.Keys; // Assert Assert.Equal(new[] { "key" }, keys); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Keys_ListStorage() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -702,42 +702,42 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.Equal(new[] { "key" }, keys); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Values_EmptyStorage() { // Arrange - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); // Act var values = dict.Values; // Assert Assert.Empty(values); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Values_PropertyStorage() { // Arrange - var dict = new RouteValueDictionary(new { key = "value", }); + var dict = new DispatcherValueCollection(new { key = "value", }); // Act var values = dict.Values; // Assert Assert.Equal(new object[] { "value" }, values); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Values_ListStorage() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -747,28 +747,28 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.Equal(new object[] { "value" }, values); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Add_EmptyStorage() { // Arrange - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); // Act dict.Add("key", "value"); // Assert Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Add_PropertyStorage() { // Arrange - var dict = new RouteValueDictionary(new { age = 30 }); + var dict = new DispatcherValueCollection(new { age = 30 }); // Act dict.Add("key", "value"); @@ -778,14 +778,14 @@ namespace Microsoft.AspNetCore.Routing.Tests dict.OrderBy(kvp => kvp.Key), kvp => { Assert.Equal("age", kvp.Key); Assert.Equal(30, kvp.Value); }, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Add_ListStorage() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "age", 30 }, }; @@ -798,19 +798,19 @@ namespace Microsoft.AspNetCore.Routing.Tests dict.OrderBy(kvp => kvp.Key), kvp => { Assert.Equal("age", kvp.Key); Assert.Equal(30, kvp.Value); }, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Add_DuplicateKey() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; - var message = $"An element with the key 'key' already exists in the {nameof(RouteValueDictionary)}"; + var message = $"An element with the key 'key' already exists in the {nameof(DispatcherValueCollection)}"; // Act & Assert ExceptionAssert.ThrowsArgument(() => dict.Add("key", "value2"), "key", message); @@ -819,19 +819,19 @@ namespace Microsoft.AspNetCore.Routing.Tests Assert.Collection( dict.OrderBy(kvp => kvp.Key), kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Add_DuplicateKey_CaseInsensitive() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; - var message = $"An element with the key 'kEy' already exists in the {nameof(RouteValueDictionary)}"; + var message = $"An element with the key 'kEy' already exists in the {nameof(DispatcherValueCollection)}"; // Act & Assert ExceptionAssert.ThrowsArgument(() => dict.Add("kEy", "value2"), "key", message); @@ -840,14 +840,14 @@ namespace Microsoft.AspNetCore.Routing.Tests Assert.Collection( dict.OrderBy(kvp => kvp.Key), kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Add_KeyValuePair() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "age", 30 }, }; @@ -860,56 +860,56 @@ namespace Microsoft.AspNetCore.Routing.Tests dict.OrderBy(kvp => kvp.Key), kvp => { Assert.Equal("age", kvp.Key); Assert.Equal(30, kvp.Value); }, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Clear_EmptyStorage() { // Arrange - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); // Act dict.Clear(); // Assert Assert.Empty(dict); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Clear_PropertyStorage_AlreadyEmpty() { // Arrange - var dict = new RouteValueDictionary(new { }); + var dict = new DispatcherValueCollection(new { }); // Act dict.Clear(); // Assert Assert.Empty(dict); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Clear_PropertyStorage() { // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); + var dict = new DispatcherValueCollection(new { key = "value" }); // Act dict.Clear(); // Assert Assert.Empty(dict); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Clear_ListStorage() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -919,14 +919,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.Empty(dict); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Contains_KeyValuePair_True() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -938,14 +938,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.True(result); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Contains_KeyValuePair_True_CaseInsensitive() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -957,14 +957,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.True(result); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Contains_KeyValuePair_False() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -976,7 +976,7 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.False(result); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } // Value comparisons use the default equality comparer. @@ -984,7 +984,7 @@ namespace Microsoft.AspNetCore.Routing.Tests public void Contains_KeyValuePair_False_ValueComparisonIsDefault() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -996,70 +996,70 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.False(result); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void ContainsKey_EmptyStorage() { // Arrange - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); // Act var result = dict.ContainsKey("key"); // Assert Assert.False(result); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void ContainsKey_PropertyStorage_False() { // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); + var dict = new DispatcherValueCollection(new { key = "value" }); // Act var result = dict.ContainsKey("other"); // Assert Assert.False(result); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void ContainsKey_PropertyStorage_True() { // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); + var dict = new DispatcherValueCollection(new { key = "value" }); // Act var result = dict.ContainsKey("key"); // Assert Assert.True(result); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void ContainsKey_PropertyStorage_True_CaseInsensitive() { // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); + var dict = new DispatcherValueCollection(new { key = "value" }); // Act var result = dict.ContainsKey("kEy"); // Assert Assert.True(result); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void ContainsKey_ListStorage_False() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -1069,14 +1069,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.False(result); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void ContainsKey_ListStorage_True() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -1086,14 +1086,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.True(result); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void ContainsKey_ListStorage_True_CaseInsensitive() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -1103,14 +1103,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.True(result); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void CopyTo() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -1128,14 +1128,14 @@ namespace Microsoft.AspNetCore.Routing.Tests new KeyValuePair("key", "value") }, array); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Remove_KeyValuePair_True() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -1148,14 +1148,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.True(result); Assert.Empty(dict); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Remove_KeyValuePair_True_CaseInsensitive() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -1168,14 +1168,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.True(result); Assert.Empty(dict); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Remove_KeyValuePair_False() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -1188,7 +1188,7 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.False(result); Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } // Value comparisons use the default equality comparer. @@ -1196,7 +1196,7 @@ namespace Microsoft.AspNetCore.Routing.Tests public void Remove_KeyValuePair_False_ValueComparisonIsDefault() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -1209,28 +1209,28 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.False(result); Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Remove_EmptyStorage() { // Arrange - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); // Act var result = dict.Remove("key"); // Assert Assert.False(result); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Remove_PropertyStorage_Empty() { // Arrange - var dict = new RouteValueDictionary(new { }); + var dict = new DispatcherValueCollection(new { }); // Act var result = dict.Remove("other"); @@ -1238,14 +1238,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.False(result); Assert.Empty(dict); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Remove_PropertyStorage_False() { // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); + var dict = new DispatcherValueCollection(new { key = "value" }); // Act var result = dict.Remove("other"); @@ -1253,14 +1253,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.False(result); Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Remove_PropertyStorage_True() { // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); + var dict = new DispatcherValueCollection(new { key = "value" }); // Act var result = dict.Remove("key"); @@ -1268,14 +1268,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.True(result); Assert.Empty(dict); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Remove_PropertyStorage_True_CaseInsensitive() { // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); + var dict = new DispatcherValueCollection(new { key = "value" }); // Act var result = dict.Remove("kEy"); @@ -1283,14 +1283,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.True(result); Assert.Empty(dict); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Remove_ListStorage_False() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -1301,14 +1301,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.False(result); Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); }); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Remove_ListStorage_True() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -1319,14 +1319,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.True(result); Assert.Empty(dict); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void Remove_ListStorage_True_CaseInsensitive() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -1337,14 +1337,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.True(result); Assert.Empty(dict); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void TryGetValue_EmptyStorage() { // Arrange - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); // Act object value; @@ -1353,14 +1353,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.False(result); Assert.Null(value); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void TryGetValue_PropertyStorage_False() { // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); + var dict = new DispatcherValueCollection(new { key = "value" }); // Act object value; @@ -1369,14 +1369,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.False(result); Assert.Null(value); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void TryGetValue_PropertyStorage_True() { // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); + var dict = new DispatcherValueCollection(new { key = "value" }); // Act object value; @@ -1385,14 +1385,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.True(result); Assert.Equal("value", value); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void TryGetValue_PropertyStorage_True_CaseInsensitive() { // Arrange - var dict = new RouteValueDictionary(new { key = "value" }); + var dict = new DispatcherValueCollection(new { key = "value" }); // Act object value; @@ -1401,14 +1401,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.True(result); Assert.Equal("value", value); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void TryGetValue_ListStorage_False() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -1420,14 +1420,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.False(result); Assert.Null(value); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void TryGetValue_ListStorage_True() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -1439,14 +1439,14 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.True(result); Assert.Equal("value", value); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void TryGetValue_ListStorage_True_CaseInsensitive() { // Arrange - var dict = new RouteValueDictionary() + var dict = new DispatcherValueCollection() { { "key", "value" }, }; @@ -1458,20 +1458,20 @@ namespace Microsoft.AspNetCore.Routing.Tests // Assert Assert.True(result); Assert.Equal("value", value); - Assert.IsType(dict._storage); + Assert.IsType(dict._storage); } [Fact] public void ListStorage_DynamicallyAdjustsCapacity() { // Arrange - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); // Act 1 dict.Add("key", "value"); // Assert 1 - var storage = Assert.IsType(dict._storage); + var storage = Assert.IsType(dict._storage); Assert.Equal(4, storage.Capacity); // Act 2 @@ -1488,13 +1488,13 @@ namespace Microsoft.AspNetCore.Routing.Tests public void ListStorage_RemoveAt_RearrangesInnerArray() { // Arrange - var dict = new RouteValueDictionary(); + var dict = new DispatcherValueCollection(); dict.Add("key", "value"); dict.Add("key2", "value2"); dict.Add("key3", "value3"); // Assert 1 - var storage = Assert.IsType(dict._storage); + var storage = Assert.IsType(dict._storage); Assert.Equal(3, storage.Count); // Act