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