diff options
author | bradwilson <dotnetguy@gmail.com> | 2012-03-23 03:16:25 +0400 |
---|---|---|
committer | bradwilson <dotnetguy@gmail.com> | 2012-03-27 02:39:15 +0400 |
commit | b3638e50c6369c0ccd49ed74d84342b26c95d782 (patch) | |
tree | 145b63cc6362f7107a683e7f81bbef0e9afbeefb /src/System.Web.Mvc | |
parent | 2f53e34a549fca4024fbe1d91e2d5c6881115b9c (diff) |
383115/383116: Faster model binding prefix handling
Diffstat (limited to 'src/System.Web.Mvc')
-rw-r--r-- | src/System.Web.Mvc/DictionaryValueProvider.cs (renamed from src/System.Web.Mvc/DictionaryValueProvider`1.cs) | 27 | ||||
-rw-r--r-- | src/System.Web.Mvc/NameValueCollectionValueProvider.cs | 27 | ||||
-rw-r--r-- | src/System.Web.Mvc/System.Web.Mvc.csproj | 5 | ||||
-rw-r--r-- | src/System.Web.Mvc/ValueProviderUtil.cs | 83 |
4 files changed, 17 insertions, 125 deletions
diff --git a/src/System.Web.Mvc/DictionaryValueProvider`1.cs b/src/System.Web.Mvc/DictionaryValueProvider.cs index d1abfa94..5a442aa7 100644 --- a/src/System.Web.Mvc/DictionaryValueProvider`1.cs +++ b/src/System.Web.Mvc/DictionaryValueProvider.cs @@ -5,7 +5,7 @@ namespace System.Web.Mvc { public class DictionaryValueProvider<TValue> : IValueProvider, IEnumerableValueProvider { - private readonly HashSet<string> _prefixes = new HashSet<string>(StringComparer.OrdinalIgnoreCase); + private readonly Lazy<PrefixContainer> _prefixContainer; private readonly Dictionary<string, ValueProviderResult> _values = new Dictionary<string, ValueProviderResult>(StringComparer.OrdinalIgnoreCase); public DictionaryValueProvider(IDictionary<string, TValue> dictionary, CultureInfo culture) @@ -15,34 +15,19 @@ namespace System.Web.Mvc throw new ArgumentNullException("dictionary"); } - AddValues(dictionary, culture); - } - - private void AddValues(IDictionary<string, TValue> dictionary, CultureInfo culture) - { - if (dictionary.Count > 0) - { - _prefixes.Add(String.Empty); - } - - foreach (var entry in dictionary) + foreach (KeyValuePair<string, TValue> entry in dictionary) { - _prefixes.UnionWith(ValueProviderUtil.GetPrefixes(entry.Key)); - object rawValue = entry.Value; string attemptedValue = Convert.ToString(rawValue, culture); _values[entry.Key] = new ValueProviderResult(rawValue, attemptedValue, culture); } + + _prefixContainer = new Lazy<PrefixContainer>(() => new PrefixContainer(_values.Keys), isThreadSafe: true); } public virtual bool ContainsPrefix(string prefix) { - if (prefix == null) - { - throw new ArgumentNullException("prefix"); - } - - return _prefixes.Contains(prefix); + return _prefixContainer.Value.ContainsPrefix(prefix); } public virtual ValueProviderResult GetValue(string key) @@ -59,7 +44,7 @@ namespace System.Web.Mvc public virtual IDictionary<string, string> GetKeysFromPrefix(string prefix) { - return ValueProviderUtil.GetKeysFromPrefix(_prefixes, prefix); + return _prefixContainer.Value.GetKeysFromPrefix(prefix); } } } diff --git a/src/System.Web.Mvc/NameValueCollectionValueProvider.cs b/src/System.Web.Mvc/NameValueCollectionValueProvider.cs index 0db898e2..f9ea26a9 100644 --- a/src/System.Web.Mvc/NameValueCollectionValueProvider.cs +++ b/src/System.Web.Mvc/NameValueCollectionValueProvider.cs @@ -7,11 +7,11 @@ namespace System.Web.Mvc { public class NameValueCollectionValueProvider : IValueProvider, IUnvalidatedValueProvider, IEnumerableValueProvider { - private readonly HashSet<string> _prefixes = new HashSet<string>(StringComparer.OrdinalIgnoreCase); + private readonly Lazy<PrefixContainer> _prefixContainer; private readonly Dictionary<string, ValueProviderResultPlaceholder> _values = new Dictionary<string, ValueProviderResultPlaceholder>(StringComparer.OrdinalIgnoreCase); public NameValueCollectionValueProvider(NameValueCollection collection, CultureInfo culture) - : this(collection, null /* unvalidatedCollection */, culture) + : this(collection, unvalidatedCollection: null, culture: culture) { } @@ -22,40 +22,27 @@ namespace System.Web.Mvc throw new ArgumentNullException("collection"); } - AddValues(collection, unvalidatedCollection ?? collection, culture); - } + unvalidatedCollection = unvalidatedCollection ?? collection; - private void AddValues(NameValueCollection validatedCollection, NameValueCollection unvalidatedCollection, CultureInfo culture) - { // Need to read keys from the unvalidated collection, as M.W.I's granular request validation is a bit touchy // and validated entries at the time the key or value is looked at. For example, GetKey() will throw if the // value fails request validation, even though the value's not being looked at (M.W.I can't tell the difference). - if (unvalidatedCollection.Count > 0) - { - _prefixes.Add(String.Empty); - } + _prefixContainer = new Lazy<PrefixContainer>(() => new PrefixContainer(unvalidatedCollection.AllKeys), isThreadSafe: true); foreach (string key in unvalidatedCollection) { if (key != null) { - _prefixes.UnionWith(ValueProviderUtil.GetPrefixes(key)); - // need to look up values lazily, as eagerly looking at the collection might trigger validation - _values[key] = new ValueProviderResultPlaceholder(key, validatedCollection, unvalidatedCollection, culture); + _values[key] = new ValueProviderResultPlaceholder(key, collection, unvalidatedCollection, culture); } } } public virtual bool ContainsPrefix(string prefix) { - if (prefix == null) - { - throw new ArgumentNullException("prefix"); - } - - return _prefixes.Contains(prefix); + return _prefixContainer.Value.ContainsPrefix(prefix); } public virtual ValueProviderResult GetValue(string key) @@ -84,7 +71,7 @@ namespace System.Web.Mvc public virtual IDictionary<string, string> GetKeysFromPrefix(string prefix) { - return ValueProviderUtil.GetKeysFromPrefix(_prefixes, prefix); + return _prefixContainer.Value.GetKeysFromPrefix(prefix); } // Placeholder that can store a validated (in relation to request validation) or unvalidated diff --git a/src/System.Web.Mvc/System.Web.Mvc.csproj b/src/System.Web.Mvc/System.Web.Mvc.csproj index eb19b321..7b8cb5c0 100644 --- a/src/System.Web.Mvc/System.Web.Mvc.csproj +++ b/src/System.Web.Mvc/System.Web.Mvc.csproj @@ -67,6 +67,9 @@ <Compile Include="..\CommonAssemblyInfo.cs"> <Link>Properties\CommonAssemblyInfo.cs</Link> </Compile> + <Compile Include="..\Common\PrefixContainer.cs"> + <Link>Common\PrefixContainer.cs</Link> + </Compile> <Compile Include="..\Common\TaskHelpers.cs"> <Link>Common\TaskHelpers.cs</Link> </Compile> @@ -229,7 +232,7 @@ <Compile Include="ValueProviderFactory.cs" /> <Compile Include="ValueProviderFactoryCollection.cs" /> <Compile Include="ValueProviderCollection.cs" /> - <Compile Include="DictionaryValueProvider`1.cs" /> + <Compile Include="DictionaryValueProvider.cs" /> <Compile Include="NameValueCollectionValueProvider.cs" /> <Compile Include="ValueProviderUtil.cs" /> <Compile Include="IValueProvider.cs" /> diff --git a/src/System.Web.Mvc/ValueProviderUtil.cs b/src/System.Web.Mvc/ValueProviderUtil.cs index 3a56a3c8..1bc1b738 100644 --- a/src/System.Web.Mvc/ValueProviderUtil.cs +++ b/src/System.Web.Mvc/ValueProviderUtil.cs @@ -4,26 +4,6 @@ namespace System.Web.Mvc { internal static class ValueProviderUtil { - // Given "foo.bar[baz].quux", this method will return: - // - "foo.bar[baz].quux" - // - "foo.bar[baz]" - // - "foo.bar" - // - "foo" - public static IEnumerable<string> GetPrefixes(string key) - { - yield return key; - for (int i = key.Length - 1; i >= 0; i--) - { - switch (key[i]) - { - case '.': - case '[': - yield return key.Substring(0, i); - break; - } - } - } - public static bool CollectionContainsPrefix(IEnumerable<string> collection, string prefix) { foreach (string key in collection) @@ -56,68 +36,5 @@ namespace System.Web.Mvc return false; // nothing found } - - // Given "foo.bar", "foo.hello", "something.other", foo[abc].baz and asking for prefix "foo" will return: - // - "bar"/"foo.bar" - // - "hello"/"foo.hello" - // - "abc"/"foo[abc]" - public static IDictionary<string, string> GetKeysFromPrefix(IEnumerable<string> collection, string prefix) - { - IDictionary<string, string> keys = new Dictionary<string, string>(); - foreach (var entry in collection) - { - if (entry != null) - { - string key = null; - string fullName = null; - - if (entry.Length == prefix.Length) - { - // No key in this entry - continue; - } - - if (entry.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) - { - int keyPosition = prefix.Length + 1; - switch (entry[prefix.Length]) - { - case '.': - int dotPosition = entry.IndexOf('.', keyPosition); - if (dotPosition == -1) - { - dotPosition = entry.Length; - } - - key = entry.Substring(keyPosition, dotPosition - keyPosition); - fullName = entry.Substring(0, dotPosition); - break; - - case '[': - int bracketPosition = entry.IndexOf(']', keyPosition); - if (bracketPosition == -1) - { - // Malformed for dictionary - continue; - } - - key = entry.Substring(keyPosition, bracketPosition - keyPosition); - fullName = entry.Substring(0, bracketPosition + 1); - break; - - default: - continue; - } - - if (!keys.ContainsKey(key)) - { - keys.Add(key, fullName); - } - } - } - } - - return keys; - } } } |