// 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.Contracts; using System.Globalization; using System.Threading.Tasks; using Microsoft.AspNet.Http; using Microsoft.AspNet.Mvc.ModelBinding.Internal; namespace Microsoft.AspNet.Mvc.ModelBinding { public class ReadableStringCollectionValueProvider : MarkerAwareValueProvider, IEnumerableValueProvider where TBinderMarker : IValueBinderMarker { private readonly CultureInfo _culture; private PrefixContainer _prefixContainer; private readonly Func> _valuesFactory; private IReadableStringCollection _values; /// /// Creates a NameValuePairsProvider wrapping an existing set of key value pairs. /// /// The key value pairs to wrap. /// The culture to return with ValueProviderResult instances. public ReadableStringCollectionValueProvider([NotNull] IReadableStringCollection values, CultureInfo culture) { _values = values; _culture = culture; } public ReadableStringCollectionValueProvider([NotNull] Func> valuesFactory, CultureInfo culture) { _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) { Contract.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; } } }