1 /* ****************************************************************************
\r
3 * Copyright (c) Microsoft Corporation. All rights reserved.
\r
5 * This software is subject to the Microsoft Public License (Ms-PL).
\r
6 * A copy of the license can be found in the license.htm file included
\r
7 * in this distribution.
\r
9 * You must not remove this notice, or any other, from this software.
\r
11 * ***************************************************************************/
\r
13 namespace System.Web.Mvc {
\r
15 using System.Collections;
\r
16 using System.ComponentModel;
\r
17 using System.Globalization;
\r
18 using System.Web.Mvc.Resources;
\r
21 public class ValueProviderResult {
\r
23 private static readonly CultureInfo _staticCulture = CultureInfo.InvariantCulture;
\r
24 private CultureInfo _instanceCulture;
\r
26 // default constructor so that subclassed types can set the properties themselves
\r
27 protected ValueProviderResult() {
\r
30 public ValueProviderResult(object rawValue, string attemptedValue, CultureInfo culture) {
\r
31 RawValue = rawValue;
\r
32 AttemptedValue = attemptedValue;
\r
36 public string AttemptedValue {
\r
41 public CultureInfo Culture {
\r
43 if (_instanceCulture == null) {
\r
44 _instanceCulture = _staticCulture;
\r
46 return _instanceCulture;
\r
49 _instanceCulture = value;
\r
53 public object RawValue {
\r
58 private static object ConvertSimpleType(CultureInfo culture, object value, Type destinationType) {
\r
59 if (value == null || destinationType.IsInstanceOfType(value)) {
\r
63 // if this is a user-input value but the user didn't type anything, return no value
\r
64 string valueAsString = value as string;
\r
65 if (valueAsString != null && valueAsString.Trim().Length == 0) {
\r
69 TypeConverter converter = TypeDescriptor.GetConverter(destinationType);
\r
70 bool canConvertFrom = converter.CanConvertFrom(value.GetType());
\r
71 if (!canConvertFrom) {
\r
72 converter = TypeDescriptor.GetConverter(value.GetType());
\r
74 if (!(canConvertFrom || converter.CanConvertTo(destinationType))) {
\r
75 string message = String.Format(CultureInfo.CurrentUICulture, MvcResources.ValueProviderResult_NoConverterExists,
\r
76 value.GetType().FullName, destinationType.FullName);
\r
77 throw new InvalidOperationException(message);
\r
81 object convertedValue = (canConvertFrom) ?
\r
82 converter.ConvertFrom(null /* context */, culture, value) :
\r
83 converter.ConvertTo(null /* context */, culture, value, destinationType);
\r
84 return convertedValue;
\r
86 catch (Exception ex) {
\r
87 string message = String.Format(CultureInfo.CurrentUICulture, MvcResources.ValueProviderResult_ConversionThrew,
\r
88 value.GetType().FullName, destinationType.FullName);
\r
89 throw new InvalidOperationException(message, ex);
\r
93 public object ConvertTo(Type type) {
\r
94 return ConvertTo(type, null /* culture */);
\r
97 public virtual object ConvertTo(Type type, CultureInfo culture) {
\r
99 throw new ArgumentNullException("type");
\r
102 CultureInfo cultureToUse = culture ?? Culture;
\r
103 return UnwrapPossibleArrayType(cultureToUse, RawValue, type);
\r
106 private static object UnwrapPossibleArrayType(CultureInfo culture, object value, Type destinationType) {
\r
107 if (value == null || destinationType.IsInstanceOfType(value)) {
\r
111 // array conversion results in four cases, as below
\r
112 Array valueAsArray = value as Array;
\r
113 if (destinationType.IsArray) {
\r
114 Type destinationElementType = destinationType.GetElementType();
\r
115 if (valueAsArray != null) {
\r
116 // case 1: both destination + source type are arrays, so convert each element
\r
117 IList converted = Array.CreateInstance(destinationElementType, valueAsArray.Length);
\r
118 for (int i = 0; i < valueAsArray.Length; i++) {
\r
119 converted[i] = ConvertSimpleType(culture, valueAsArray.GetValue(i), destinationElementType);
\r
124 // case 2: destination type is array but source is single element, so wrap element in array + convert
\r
125 object element = ConvertSimpleType(culture, value, destinationElementType);
\r
126 IList converted = Array.CreateInstance(destinationElementType, 1);
\r
127 converted[0] = element;
\r
131 else if (valueAsArray != null) {
\r
132 // case 3: destination type is single element but source is array, so extract first element + convert
\r
133 if (valueAsArray.Length > 0) {
\r
134 value = valueAsArray.GetValue(0);
\r
135 return ConvertSimpleType(culture, value, destinationType);
\r
138 // case 3(a): source is empty array, so can't perform conversion
\r
142 // case 4: both destination + source type are single elements, so convert
\r
143 return ConvertSimpleType(culture, value, destinationType);
\r