1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
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;
}
}
}
|