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 136 137 138 139 140 141 142 143 144 145
|
namespace System.Web.ModelBinding {
using System;
using System.Collections;
using System.ComponentModel;
using System.Globalization;
[Serializable]
public class ValueProviderResult {
private static readonly CultureInfo _staticCulture = CultureInfo.InvariantCulture;
private CultureInfo _instanceCulture;
// default constructor so that subclassed types can set the properties themselves
protected ValueProviderResult() {
}
public ValueProviderResult(object rawValue, string attemptedValue, CultureInfo culture) {
RawValue = rawValue;
AttemptedValue = attemptedValue;
Culture = culture;
}
public string AttemptedValue {
get;
protected set;
}
public CultureInfo Culture {
get {
if (_instanceCulture == null) {
_instanceCulture = _staticCulture;
}
return _instanceCulture;
}
protected set {
_instanceCulture = value;
}
}
public object RawValue {
get;
protected set;
}
private static object ConvertSimpleType(CultureInfo culture, object value, Type destinationType) {
if (value == null || destinationType.IsInstanceOfType(value)) {
return value;
}
// if this is a user-input value but the user didn't type anything, return no value
string valueAsString = value as string;
if (valueAsString != null && valueAsString.Trim().Length == 0) {
return null;
}
TypeConverter converter = TypeDescriptor.GetConverter(destinationType);
bool canConvertFrom = converter.CanConvertFrom(value.GetType());
if (!canConvertFrom) {
converter = TypeDescriptor.GetConverter(value.GetType());
}
if (!(canConvertFrom || converter.CanConvertTo(destinationType))) {
// EnumConverter cannot convert integer, so we verify manually
if (destinationType.IsEnum && value is int) {
return Enum.ToObject(destinationType, (int)value);
}
// In case of a Nullable object, we try again with its underlying type.
Type underlyingType = Nullable.GetUnderlyingType(destinationType);
if (underlyingType != null) {
return ConvertSimpleType(culture, value, underlyingType);
}
string message = String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.ValueProviderResult_NoConverterExists),
value.GetType().FullName, destinationType.FullName);
throw new InvalidOperationException(message);
}
try {
object convertedValue = (canConvertFrom) ?
converter.ConvertFrom(null /* context */, culture, value) :
converter.ConvertTo(null /* context */, culture, value, destinationType);
return convertedValue;
}
catch (Exception ex) {
string message = String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.ValueProviderResult_ConversionThrew),
value.GetType().FullName, destinationType.FullName);
throw new InvalidOperationException(message, ex);
}
}
public object ConvertTo(Type type) {
return ConvertTo(type, null /* culture */);
}
public virtual object ConvertTo(Type type, CultureInfo culture) {
if (type == null) {
throw new ArgumentNullException("type");
}
CultureInfo cultureToUse = culture ?? Culture;
return UnwrapPossibleArrayType(cultureToUse, RawValue, type);
}
private static object UnwrapPossibleArrayType(CultureInfo culture, object value, Type destinationType) {
if (value == null || destinationType.IsInstanceOfType(value)) {
return value;
}
// array conversion results in four cases, as below
Array valueAsArray = value as Array;
if (destinationType.IsArray) {
Type destinationElementType = destinationType.GetElementType();
if (valueAsArray != null) {
// case 1: both destination + source type are arrays, so convert each element
IList converted = Array.CreateInstance(destinationElementType, valueAsArray.Length);
for (int i = 0; i < valueAsArray.Length; i++) {
converted[i] = ConvertSimpleType(culture, valueAsArray.GetValue(i), destinationElementType);
}
return converted;
}
else {
// case 2: destination type is array but source is single element, so wrap element in array + convert
object element = ConvertSimpleType(culture, value, destinationElementType);
IList converted = Array.CreateInstance(destinationElementType, 1);
converted[0] = element;
return converted;
}
}
else if (valueAsArray != null) {
// case 3: destination type is single element but source is array, so extract first element + convert
if (valueAsArray.Length > 0) {
value = valueAsArray.GetValue(0);
return ConvertSimpleType(culture, value, destinationType);
}
else {
// case 3(a): source is empty array, so can't perform conversion
return null;
}
}
// case 4: both destination + source type are single elements, so convert
return ConvertSimpleType(culture, value, destinationType);
}
}
}
|