Fix RouteValueDictionary to handle read-only dictionaries.

This commit is contained in:
Kiran Challa 2015-05-01 06:25:03 -07:00
parent f6e48d0080
commit 1f6d3fe4cc
3 changed files with 69 additions and 20 deletions

View File

@ -23,7 +23,7 @@ namespace Microsoft.AspNet.Routing
private readonly Dictionary<string, object> _dictionary; private readonly Dictionary<string, object> _dictionary;
/// <summary> /// <summary>
/// Creates an empty RouteValueDictionary. /// Creates an empty <see cref="RouteValueDictionary"/>.
/// </summary> /// </summary>
public RouteValueDictionary() public RouteValueDictionary()
{ {
@ -31,28 +31,32 @@ namespace Microsoft.AspNet.Routing
} }
/// <summary> /// <summary>
/// Creates a RouteValueDictionary initialized with the provided input values. /// Creates a <see cref="RouteValueDictionary"/> initialized with the provided input value.
/// </summary> /// </summary>
/// <param name="values">Input values to copy into the dictionary.</param> /// <param name="obj">An object to initialize the dictionary. The value can be of type
public RouteValueDictionary([NotNull] IDictionary<string, object> values) /// <see cref="IDictionary{TKey, TValue}"/> or <see cref="IReadOnlyDictionary{TKey, TValue}"/> or
{ /// any other object.
_dictionary = new Dictionary<string, object>(values, StringComparer.OrdinalIgnoreCase); /// </param>
}
/// <summary>
/// Creates a RouteValueDictionary initialized with the provided input values.
/// </summary>
/// <param name="values">Input values to copy into the dictionary.</param>
/// <remarks> /// <remarks>
/// The input parameter is interpreted as a set of key-value-pairs where the property names /// If the value is a dictionary, then its entries are copied. Otherwise the object is interpreted as a set
/// are keys, and property values are the values, and copied into the dictionary. Only public /// of key-value-pairs where the property names are keys, and property values are the values, and copied
/// instance non-index properties are considered. /// into the dictionary. Only public instance non-index properties are considered.
/// </remarks> /// </remarks>
public RouteValueDictionary(object obj) public RouteValueDictionary(object obj)
: this() : this()
{ {
if (obj != null) if (obj != null)
{ {
var keyValuePairCollection = obj as IEnumerable<KeyValuePair<string, object>>;
if (keyValuePairCollection != null)
{
foreach (var kvp in keyValuePairCollection)
{
Add(kvp.Key, kvp.Value);
}
return;
}
var type = obj.GetType(); var type = obj.GetType();
var allProperties = type.GetRuntimeProperties(); var allProperties = type.GetRuntimeProperties();

View File

@ -370,11 +370,7 @@ namespace Microsoft.AspNet.Routing.Template
if (_defaults != null) if (_defaults != null)
{ {
_filters = new RouteValueDictionary(defaults); _filters = new RouteValueDictionary(_defaults);
foreach (var kvp in _defaults)
{
_filters.Add(kvp.Key, kvp.Value);
}
} }
} }

View File

@ -168,6 +168,48 @@ namespace Microsoft.AspNet.Routing.Tests
expected); expected);
} }
[Fact]
public void CreateFromReadOnlyDictionary_CopiesValues()
{
// Arrange
var dictionary = new Dictionary<string, object>();
dictionary.Add("Name", "James");
dictionary.Add("Age", 30);
var readonlyDictionary = (IReadOnlyDictionary<string, object>)dictionary;
// Act
var dict = new RouteValueDictionary(readonlyDictionary);
// Assert
Assert.Equal(2, dict.Count);
Assert.Equal("James", dict["Name"]);
Assert.Equal(30, dict["Age"]);
}
[Fact]
public void CreateFromReadOnlyDictionary_ModifyRouteValueDictionary()
{
// Arrange
var dictionary = new Dictionary<string, object>();
dictionary.Add("Name", "James");
dictionary.Add("Age", 30);
dictionary.Add("Address", new Address() { City = "Redmond", State = "WA" });
var readonlyDictionary = (IReadOnlyDictionary<string, object>)dictionary;
// Act
var routeValueDictionary = new RouteValueDictionary(readonlyDictionary);
routeValueDictionary.Add("City", "Redmond");
// Assert
Assert.Equal(4, routeValueDictionary.Count);
Assert.Equal("James", routeValueDictionary["Name"]);
Assert.Equal(30, routeValueDictionary["Age"]);
Assert.Equal("Redmond", routeValueDictionary["City"]);
var address = Assert.IsType<Address>(routeValueDictionary["Address"]);
address.State = "Washington";
Assert.Equal("Washington", ((Address)routeValueDictionary["Address"]).State);
}
private static string GetDuplicateKeyErrorMessage() private static string GetDuplicateKeyErrorMessage()
{ {
// Gets the exception message when duplicate entries are // Gets the exception message when duplicate entries are
@ -233,5 +275,12 @@ namespace Microsoft.AspNet.Routing.Tests
set { } set { }
} }
} }
private class Address
{
public string City { get; set; }
public string State { get; set; }
}
} }
} }