e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
136 lines
5.9 KiB
C#
136 lines
5.9 KiB
C#
namespace System.Web.ModelBinding {
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
|
|
public sealed class ModelBinderProviderCollection : Collection<ModelBinderProvider> {
|
|
|
|
public ModelBinderProviderCollection() {
|
|
}
|
|
|
|
public ModelBinderProviderCollection(IList<ModelBinderProvider> list)
|
|
: base(list) {
|
|
}
|
|
|
|
public IModelBinder GetBinder(ModelBindingExecutionContext modelBindingExecutionContext, ModelBindingContext bindingContext) {
|
|
if (modelBindingExecutionContext == null) {
|
|
throw new ArgumentNullException("modelBindingExecutionContext");
|
|
}
|
|
if (bindingContext == null) {
|
|
throw new ArgumentNullException("bindingContext");
|
|
}
|
|
|
|
ModelBinderProvider providerFromAttr;
|
|
if (TryGetProviderFromAttributes(bindingContext.ModelType, out providerFromAttr)) {
|
|
return providerFromAttr.GetBinder(modelBindingExecutionContext, bindingContext);
|
|
}
|
|
|
|
return (from provider in this
|
|
let binder = provider.GetBinder(modelBindingExecutionContext, bindingContext)
|
|
where binder != null
|
|
select binder).FirstOrDefault();
|
|
}
|
|
|
|
internal IModelBinder GetRequiredBinder(ModelBindingExecutionContext modelBindingExecutionContext, ModelBindingContext bindingContext) {
|
|
IModelBinder binder = GetBinder(modelBindingExecutionContext, bindingContext);
|
|
if (binder == null) {
|
|
throw Error.ModelBinderProviderCollection_BinderForTypeNotFound(bindingContext.ModelType);
|
|
}
|
|
return binder;
|
|
}
|
|
|
|
protected override void InsertItem(int index, ModelBinderProvider item) {
|
|
if (item == null) {
|
|
throw new ArgumentNullException("item");
|
|
}
|
|
|
|
base.InsertItem(index, item);
|
|
}
|
|
|
|
private void InsertSimpleProviderAtFront(ModelBinderProvider provider) {
|
|
// Don't want to insert simple providers before any that are marked as "should go first,"
|
|
// as that might throw off other providers like the exact type match provider.
|
|
|
|
int i = 0;
|
|
for (; i < Count; i++) {
|
|
if (!ShouldProviderGoFirst(this[i])) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
base.InsertItem(i, provider);
|
|
}
|
|
|
|
public void RegisterBinderForGenericType(Type modelType, IModelBinder modelBinder) {
|
|
InsertSimpleProviderAtFront(new GenericModelBinderProvider(modelType, modelBinder));
|
|
}
|
|
|
|
public void RegisterBinderForGenericType(Type modelType, Func<Type[], IModelBinder> modelBinderFactory) {
|
|
InsertSimpleProviderAtFront(new GenericModelBinderProvider(modelType, modelBinderFactory));
|
|
}
|
|
|
|
public void RegisterBinderForGenericType(Type modelType, Type modelBinderType) {
|
|
InsertSimpleProviderAtFront(new GenericModelBinderProvider(modelType, modelBinderType));
|
|
}
|
|
|
|
public void RegisterBinderForType(Type modelType, IModelBinder modelBinder) {
|
|
RegisterBinderForType(modelType, modelBinder, false /* suppressPrefixCheck */);
|
|
}
|
|
|
|
internal void RegisterBinderForType(Type modelType, IModelBinder modelBinder, bool suppressPrefixCheck) {
|
|
SimpleModelBinderProvider provider = new SimpleModelBinderProvider(modelType, modelBinder) {
|
|
SuppressPrefixCheck = suppressPrefixCheck
|
|
};
|
|
InsertSimpleProviderAtFront(provider);
|
|
}
|
|
|
|
public void RegisterBinderForType(Type modelType, Func<IModelBinder> modelBinderFactory) {
|
|
InsertSimpleProviderAtFront(new SimpleModelBinderProvider(modelType, modelBinderFactory));
|
|
}
|
|
|
|
protected override void SetItem(int index, ModelBinderProvider item) {
|
|
if (item == null) {
|
|
throw new ArgumentNullException("item");
|
|
}
|
|
|
|
base.SetItem(index, item);
|
|
}
|
|
|
|
private static bool ShouldProviderGoFirst(ModelBinderProvider provider) {
|
|
ModelBinderProviderOptionsAttribute options = provider.GetType()
|
|
.GetCustomAttributes(typeof(ModelBinderProviderOptionsAttribute), true /* inherit */)
|
|
.OfType<ModelBinderProviderOptionsAttribute>()
|
|
.FirstOrDefault();
|
|
|
|
return (options != null) ? options.FrontOfList : false;
|
|
}
|
|
|
|
private static bool TryGetProviderFromAttributes(Type modelType, out ModelBinderProvider provider) {
|
|
ExtensibleModelBinderAttribute attr = TypeDescriptorHelper.Get(modelType).GetAttributes().OfType<ExtensibleModelBinderAttribute>().FirstOrDefault();
|
|
if (attr == null) {
|
|
provider = null;
|
|
return false;
|
|
}
|
|
|
|
if (typeof(ModelBinderProvider).IsAssignableFrom(attr.BinderType)) {
|
|
provider = (ModelBinderProvider)SecurityUtils.SecureCreateInstance(attr.BinderType);
|
|
}
|
|
else if (typeof(IModelBinder).IsAssignableFrom(attr.BinderType)) {
|
|
Type closedBinderType = (attr.BinderType.IsGenericTypeDefinition) ? attr.BinderType.MakeGenericType(modelType.GetGenericArguments()) : attr.BinderType;
|
|
IModelBinder binderInstance = (IModelBinder)SecurityUtils.SecureCreateInstance(closedBinderType);
|
|
provider = new SimpleModelBinderProvider(modelType, binderInstance) { SuppressPrefixCheck = attr.SuppressPrefixCheck };
|
|
}
|
|
else {
|
|
string errorMessage = String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.ModelBinderProviderCollection_InvalidBinderType),
|
|
attr.BinderType, typeof(ModelBinderProvider), typeof(IModelBinder));
|
|
throw new InvalidOperationException(errorMessage);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
}
|
|
}
|