// 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.Generic; using System.Diagnostics; using System.Globalization; using System.Threading.Tasks; using Microsoft.AspNet.Http; using Microsoft.AspNet.Mvc.ModelBinding.Internal; namespace Microsoft.AspNet.Mvc.ModelBinding { /// /// An adapter for data stored in an . /// public class ReadableStringCollectionValueProvider : BindingSourceValueProvider, IEnumerableValueProvider { private readonly CultureInfo _culture; private readonly Func> _valuesFactory; private PrefixContainer _prefixContainer; private IReadableStringCollection _values; /// /// Creates a provider for wrapping an existing set of key value pairs. /// /// The for the data. /// The key value pairs to wrap. /// The culture to return with ValueProviderResult instances. public ReadableStringCollectionValueProvider( [NotNull] BindingSource bindingSource, [NotNull] IReadableStringCollection values, CultureInfo culture) : base(bindingSource) { _values = values; _culture = culture; } /// /// Creates a provider for wrapping an /// existing set of key value pairs provided by the delegate. /// /// The for the data. /// The delegate that provides the key value pairs to wrap. /// The culture to return with ValueProviderResult instances. public ReadableStringCollectionValueProvider( [NotNull] BindingSource bindingSource, [NotNull] Func> valuesFactory, CultureInfo culture) : base(bindingSource) { _valuesFactory = valuesFactory; _culture = culture; } public CultureInfo Culture { get { return _culture; } } /// public override async Task ContainsPrefixAsync(string prefix) { var prefixContainer = await GetPrefixContainerAsync(); return prefixContainer.ContainsPrefix(prefix); } /// public virtual async Task> GetKeysFromPrefixAsync([NotNull] string prefix) { var prefixContainer = await GetPrefixContainerAsync(); return prefixContainer.GetKeysFromPrefix(prefix); } /// public override async Task GetValueAsync([NotNull] string key) { var collection = await GetValueCollectionAsync(); var values = collection.GetValues(key); ValueProviderResult result; if (values == null) { result = null; } else if (values.Count == 1) { var value = (string)values[0]; result = new ValueProviderResult(value, value, _culture); } else { result = new ValueProviderResult(values, _values.Get(key), _culture); } return result; } private async Task GetValueCollectionAsync() { if (_values == null) { Debug.Assert(_valuesFactory != null); _values = await _valuesFactory(); } return _values; } private async Task GetPrefixContainerAsync() { if (_prefixContainer == null) { // Initialization race is OK providing data remains read-only and object identity is not significant var collection = await GetValueCollectionAsync(); _prefixContainer = new PrefixContainer(collection.Keys); } return _prefixContainer; } } }