Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@ -0,0 +1,147 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Web.Http.Metadata;
using System.Web.Http.ModelBinding;
using System.Web.Http.ValueProviders;
namespace System.Web.Http.Internal
{
internal static class CollectionModelBinderUtil
{
internal static void CreateOrReplaceCollection<TElement>(ModelBindingContext bindingContext, IEnumerable<TElement> incomingElements, Func<ICollection<TElement>> creator)
{
ICollection<TElement> collection = bindingContext.Model as ICollection<TElement>;
if (collection == null || collection.IsReadOnly)
{
collection = creator();
bindingContext.Model = collection;
}
collection.Clear();
foreach (TElement element in incomingElements)
{
collection.Add(element);
}
}
internal static void CreateOrReplaceDictionary<TKey, TValue>(ModelBindingContext bindingContext, IEnumerable<KeyValuePair<TKey, TValue>> incomingElements, Func<IDictionary<TKey, TValue>> creator)
{
IDictionary<TKey, TValue> dictionary = bindingContext.Model as IDictionary<TKey, TValue>;
if (dictionary == null || dictionary.IsReadOnly)
{
dictionary = creator();
bindingContext.Model = dictionary;
}
dictionary.Clear();
foreach (var element in incomingElements)
{
if (element.Key != null)
{
dictionary[element.Key] = element.Value;
}
}
}
// supportedInterfaceType: type that is updatable by this binder
// newInstanceType: type that will be created by the binder if necessary
// openBinderType: model binder type
// modelMetadata: metadata for the model to bind
//
// example: GetGenericBinder(typeof(IList<>), typeof(List<>), typeof(ListBinder<>), ...) means that the ListBinder<T>
// type can update models that implement IList<T>, and if for some reason the existing model instance is not
// updatable the binder will create a List<T> object and bind to that instead. This method will return a ListBinder<T>
// or null, depending on whether the type and updatability checks succeed.
internal static IModelBinder GetGenericBinder(Type supportedInterfaceType, Type newInstanceType, Type openBinderType, ModelMetadata modelMetadata)
{
Type[] typeArguments = GetTypeArgumentsForUpdatableGenericCollection(supportedInterfaceType, newInstanceType, modelMetadata);
return (typeArguments != null) ? (IModelBinder)Activator.CreateInstance(openBinderType.MakeGenericType(typeArguments)) : null;
}
[SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.Web.Http.ValueProviders.ValueProviderResult.ConvertTo(System.Type)", Justification = "The ValueProviderResult already has the necessary context to perform a culture-aware conversion.")]
internal static IEnumerable<string> GetIndexNamesFromValueProviderResult(ValueProviderResult valueProviderResultIndex)
{
IEnumerable<string> indexNames = null;
if (valueProviderResultIndex != null)
{
string[] indexes = (string[])valueProviderResultIndex.ConvertTo(typeof(string[]));
if (indexes != null && indexes.Length > 0)
{
indexNames = indexes;
}
}
return indexNames;
}
internal static IEnumerable<string> GetZeroBasedIndexes()
{
int i = 0;
while (true)
{
yield return i.ToString(CultureInfo.InvariantCulture);
i++;
}
}
// Returns the generic type arguments for the model type if updatable, else null.
// supportedInterfaceType: open type (like IList<>) of supported interface, must implement ICollection<>
// newInstanceType: open type (like List<>) of object that will be created, must implement supportedInterfaceType
internal static Type[] GetTypeArgumentsForUpdatableGenericCollection(Type supportedInterfaceType, Type newInstanceType, ModelMetadata modelMetadata)
{
/*
* Check that we can extract proper type arguments from the model.
*/
if (!modelMetadata.ModelType.IsGenericType || modelMetadata.ModelType.IsGenericTypeDefinition)
{
// not a closed generic type
return null;
}
Type[] modelTypeArguments = modelMetadata.ModelType.GetGenericArguments();
if (modelTypeArguments.Length != supportedInterfaceType.GetGenericArguments().Length)
{
// wrong number of generic type arguments
return null;
}
/*
* Is it possible just to change the reference rather than update the collection in-place?
*/
if (!modelMetadata.IsReadOnly)
{
Type closedNewInstanceType = newInstanceType.MakeGenericType(modelTypeArguments);
if (modelMetadata.ModelType.IsAssignableFrom(closedNewInstanceType))
{
return modelTypeArguments;
}
}
/*
* At this point, we know we can't change the reference, so we need to verify that
* the model instance can be updated in-place.
*/
Type closedSupportedInterfaceType = supportedInterfaceType.MakeGenericType(modelTypeArguments);
if (!closedSupportedInterfaceType.IsInstanceOfType(modelMetadata.Model))
{
return null; // not instance of correct interface
}
Type closedCollectionType = TypeHelper.ExtractGenericInterface(closedSupportedInterfaceType, typeof(ICollection<>));
bool collectionInstanceIsReadOnly = (bool)closedCollectionType.GetProperty("IsReadOnly").GetValue(modelMetadata.Model, null);
if (collectionInstanceIsReadOnly)
{
return null;
}
else
{
return modelTypeArguments;
}
}
}
}

View File

@ -0,0 +1,74 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.ComponentModel.DataAnnotations;
using System.Security;
namespace System.Web.Http.Internal
{
// [SecuritySafeCritical] because it uses DataAnnotations types in static fields and in static method
[SecuritySafeCritical]
internal static class DataTypeUtil
{
internal static readonly string CurrencyTypeName = DataType.Currency.ToString();
internal static readonly string DateTypeName = DataType.Date.ToString();
internal static readonly string DateTimeTypeName = DataType.DateTime.ToString();
internal static readonly string DurationTypeName = DataType.Duration.ToString();
internal static readonly string EmailAddressTypeName = DataType.EmailAddress.ToString();
internal static readonly string HtmlTypeName = DataType.Html.ToString();
internal static readonly string ImageUrlTypeName = DataType.ImageUrl.ToString();
internal static readonly string MultiLineTextTypeName = DataType.MultilineText.ToString();
internal static readonly string PasswordTypeName = DataType.Password.ToString();
internal static readonly string PhoneNumberTypeName = DataType.PhoneNumber.ToString();
internal static readonly string TextTypeName = DataType.Text.ToString();
internal static readonly string TimeTypeName = DataType.Time.ToString();
internal static readonly string UrlTypeName = DataType.Url.ToString();
// This is a faster version of GetDataTypeName(). It internally calls ToString() on the enum
// value, which can be quite slow because of value verification.
internal static string ToDataTypeName(this DataTypeAttribute attribute, Func<DataTypeAttribute, Boolean> isDataType = null)
{
if (isDataType == null)
{
isDataType = t => t.GetType().Equals(typeof(DataTypeAttribute));
}
// GetDataTypeName is virtual, so this is only safe if they haven't derived from DataTypeAttribute.
// However, if they derive from DataTypeAttribute, they can help their own perf by overriding GetDataTypeName
// and returning an appropriate string without invoking the ToString() on the enum.
if (isDataType(attribute))
{
switch (attribute.DataType)
{
case DataType.Currency:
return CurrencyTypeName;
case DataType.Date:
return DateTypeName;
case DataType.DateTime:
return DateTimeTypeName;
case DataType.Duration:
return DurationTypeName;
case DataType.EmailAddress:
return EmailAddressTypeName;
case DataType.Html:
return HtmlTypeName;
case DataType.ImageUrl:
return ImageUrlTypeName;
case DataType.MultilineText:
return MultiLineTextTypeName;
case DataType.Password:
return PasswordTypeName;
case DataType.PhoneNumber:
return PhoneNumberTypeName;
case DataType.Text:
return TextTypeName;
case DataType.Time:
return TimeTypeName;
case DataType.Url:
return UrlTypeName;
}
}
return attribute.GetDataTypeName();
}
}
}

View File

@ -0,0 +1,40 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Web.Http.Controllers;
using System.Web.Http.Metadata;
using System.Web.Http.ModelBinding;
namespace System.Web.Http.Internal
{
internal static class HttpActionContextExtensions
{
public static bool TryBindStrongModel<TModel>(this HttpActionContext actionContext, ModelBindingContext parentBindingContext, string propertyName, ModelMetadataProvider metadataProvider, out TModel model)
{
if (actionContext == null)
{
throw Error.ArgumentNull("actionContext");
}
ModelBindingContext propertyBindingContext = new ModelBindingContext(parentBindingContext)
{
ModelMetadata = metadataProvider.GetMetadataForType(null, typeof(TModel)),
ModelName = ModelBindingHelper.CreatePropertyModelName(parentBindingContext.ModelName, propertyName)
};
IModelBinder binder;
if (actionContext.TryGetBinder(propertyBindingContext, out binder))
{
if (binder.BindModel(actionContext, propertyBindingContext))
{
object untypedModel = propertyBindingContext.Model;
model = ModelBindingHelper.CastOrDefault<TModel>(untypedModel);
parentBindingContext.ValidationNode.ChildNodes.Add(propertyBindingContext.ValidationNode);
return true;
}
}
model = default(TModel);
return false;
}
}
}

View File

@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Linq;
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;
using System.Web.Http.ValueProviders;
namespace System.Web.Http.Internal
{
internal static class HttpParameterBindingExtensions
{
public static bool WillReadUri(this HttpParameterBinding parameterBinding)
{
if (parameterBinding == null)
{
throw Error.ArgumentNull("parameterBinding");
}
ModelBinderParameterBinding modelParameterBinding = parameterBinding as ModelBinderParameterBinding;
if (modelParameterBinding != null)
{
if (modelParameterBinding.ValueProviderFactories.All(factory => factory is IUriValueProviderFactory))
{
return true;
}
}
return false;
}
public static bool HasDefaultValue(this HttpParameterBinding parameterBinding)
{
if (parameterBinding == null)
{
throw Error.ArgumentNull("parameterBinding");
}
return parameterBinding.Descriptor.DefaultValue != null;
}
}
}

View File

@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Reflection;
namespace System.Web.Http.Internal
{
internal static class MemberInfoExtensions
{
public static TAttribute[] GetCustomAttributes<TAttribute>(this MemberInfo member, bool inherit) where TAttribute : class
{
if (member == null)
{
throw Error.ArgumentNull("member");
}
return (TAttribute[])member.GetCustomAttributes(typeof(TAttribute), inherit);
}
}
}

View File

@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.ComponentModel;
using System.Reflection;
namespace System.Web.Http.Internal
{
internal static class ParameterInfoExtensions
{
public static TAttribute[] GetCustomAttributes<TAttribute>(this ParameterInfo parameterInfo, bool inherit) where TAttribute : class
{
if (parameterInfo == null)
{
throw Error.ArgumentNull("parameterInfo");
}
return (TAttribute[])parameterInfo.GetCustomAttributes(typeof(TAttribute), inherit);
}
public static bool TryGetDefaultValue(this ParameterInfo parameterInfo, out object value)
{
if (parameterInfo == null)
{
throw Error.ArgumentNull("parameterInfo");
}
// this will get the default value as seen by the VB / C# compilers
// if no value was baked in, RawDefaultValue returns DBNull.Value
object defaultValue = parameterInfo.DefaultValue;
if (defaultValue != DBNull.Value)
{
value = defaultValue;
return true;
}
// if the compiler did not bake in a default value, check the [DefaultValue] attribute
DefaultValueAttribute[] attrs = (DefaultValueAttribute[])parameterInfo.GetCustomAttributes(typeof(DefaultValueAttribute), false);
if (attrs == null || attrs.Length == 0)
{
value = default(object);
return false;
}
else
{
value = attrs[0].Value;
return true;
}
}
}
}

View File

@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Diagnostics.Contracts;
using System.Linq.Expressions;
namespace System.Web.Http.Internal
{
internal static class TypeActivator
{
public static Func<TBase> Create<TBase>(Type instanceType) where TBase : class
{
Contract.Assert(instanceType != null);
NewExpression newInstanceExpression = Expression.New(instanceType);
return Expression.Lambda<Func<TBase>>(newInstanceExpression).Compile();
}
public static Func<TInstance> Create<TInstance>() where TInstance : class
{
return Create<TInstance>(typeof(TInstance));
}
public static Func<object> Create(Type instanceType)
{
Contract.Assert(instanceType != null);
return Create<object>(instanceType);
}
}
}

View File

@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Security;
namespace System.Web.Http.Internal
{
// Note: DataAnnotations on 4.0 should have been a transparent assembly but is not. As a result
// we need to mark this as SecuritySafeCritical to run outside ASP (which has special knowledge
// about the DataAnnotations assembly).
[SecuritySafeCritical]
internal static class TypeDescriptorHelper
{
internal static ICustomTypeDescriptor Get(Type type)
{
return new AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type);
}
}
}

View File

@ -0,0 +1,123 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
namespace System.Web.Http.Internal
{
/// <summary>
/// A static class that provides various <see cref="Type"/> related helpers.
/// </summary>
internal static class TypeHelper
{
private static readonly Type TaskGenericType = typeof(Task<>);
internal static readonly Type HttpControllerType = typeof(IHttpController);
internal static readonly Type ApiControllerType = typeof(ApiController);
internal static Type GetTaskInnerTypeOrNull(Type type)
{
Contract.Assert(type != null);
if (type.IsGenericType && !type.IsGenericTypeDefinition)
{
Type genericTypeDefinition = type.GetGenericTypeDefinition();
// REVIEW: should we consider subclasses of Task<> ??
if (TaskGenericType == genericTypeDefinition)
{
return type.GetGenericArguments()[0];
}
}
return null;
}
internal static Type ExtractGenericInterface(Type queryType, Type interfaceType)
{
Func<Type, bool> matchesInterface = t => t.IsGenericType && t.GetGenericTypeDefinition() == interfaceType;
return matchesInterface(queryType) ? queryType : queryType.GetInterfaces().FirstOrDefault(matchesInterface);
}
internal static Type[] GetTypeArgumentsIfMatch(Type closedType, Type matchingOpenType)
{
if (!closedType.IsGenericType)
{
return null;
}
Type openType = closedType.GetGenericTypeDefinition();
return (matchingOpenType == openType) ? closedType.GetGenericArguments() : null;
}
internal static bool IsCompatibleObject(Type type, object value)
{
return (value == null && TypeAllowsNullValue(type)) || type.IsInstanceOfType(value);
}
internal static bool IsNullableValueType(Type type)
{
return Nullable.GetUnderlyingType(type) != null;
}
internal static bool TypeAllowsNullValue(Type type)
{
return !type.IsValueType || IsNullableValueType(type);
}
internal static bool IsSimpleType(Type type)
{
return type.IsPrimitive ||
type.Equals(typeof(string)) ||
type.Equals(typeof(DateTime)) ||
type.Equals(typeof(Decimal)) ||
type.Equals(typeof(Guid)) ||
type.Equals(typeof(DateTimeOffset)) ||
type.Equals(typeof(TimeSpan));
}
internal static bool IsSimpleUnderlyingType(Type type)
{
Type underlyingType = Nullable.GetUnderlyingType(type);
if (underlyingType != null)
{
type = underlyingType;
}
return TypeHelper.IsSimpleType(type);
}
internal static bool HasStringConverter(Type type)
{
return TypeDescriptor.GetConverter(type).CanConvertFrom(typeof(string));
}
/// <summary>
/// Fast implementation to get the subset of a given type.
/// </summary>
/// <typeparam name="T">type to search for</typeparam>
/// <returns>subset of objects that can be assigned to T</returns>
internal static ReadOnlyCollection<T> OfType<T>(object[] objects) where T : class
{
int max = objects.Length;
List<T> list = new List<T>(max);
int idx = 0;
for (int i = 0; i < max; i++)
{
T attr = objects[i] as T;
if (attr != null)
{
list.Add(attr);
idx++;
}
}
list.Capacity = idx;
return new ReadOnlyCollection<T>(list);
}
}
}

File diff suppressed because it is too large Load Diff