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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection;
namespace System.Web.Helpers
{
internal static class ConversionUtil
{
private static MethodInfo _stringToEnumMethod;
internal static string ToString<T>(T obj)
{
Type type = typeof(T);
if (type.IsEnum)
{
return obj.ToString();
}
TypeConverter converter = TypeDescriptor.GetConverter(type);
if ((converter != null) && (converter.CanConvertTo(typeof(string))))
{
return converter.ConvertToInvariantString(obj);
}
return null;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
Justification = "TypeConverter throws System.Exception instead of a more specific one.")]
internal static bool TryFromString(Type type, string value, out object result)
{
result = null;
if (type == typeof(string))
{
result = value;
return true;
}
if (type.IsEnum)
{
return TryFromStringToEnumHelper(type, value, out result);
}
if (type == typeof(Color))
{
Color color;
bool rval = TryFromStringToColor(value, out color);
result = color;
return rval;
}
// TypeConverter doesn't really have TryConvert APIs. We should avoid TypeConverter.IsValid
// which performs a duplicate conversion, and just handle the general exception ourselves.
TypeConverter converter = TypeDescriptor.GetConverter(type);
if ((converter != null) && converter.CanConvertFrom(typeof(string)))
{
try
{
result = converter.ConvertFromInvariantString(value);
return true;
}
catch
{
// Do nothing
}
}
return false;
}
internal static bool TryFromStringToEnum<T>(string value, out T result) where T : struct
{
return Enum.TryParse(value, ignoreCase: true, result: out result);
}
private static bool TryFromStringToEnumHelper(Type enumType, string value, out object result)
{
result = null;
if (_stringToEnumMethod == null)
{
_stringToEnumMethod = typeof(ConversionUtil).GetMethod("TryFromStringToEnum",
BindingFlags.Static | BindingFlags.NonPublic);
Debug.Assert(_stringToEnumMethod != null);
}
var args = new object[] { value, null };
var rval = (bool)_stringToEnumMethod.MakeGenericMethod(enumType).Invoke(null, args);
result = args[1];
return rval;
}
internal static bool TryFromStringToFontFamily(string fontFamily, out FontFamily result)
{
result = null;
bool converted = false;
foreach (FontFamily fontFamilyTemp in FontFamily.Families)
{
if (fontFamily.Equals(fontFamilyTemp.Name, StringComparison.OrdinalIgnoreCase))
{
result = fontFamilyTemp;
converted = true;
break;
}
}
return converted;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
Justification = "TypeConverter throws System.Exception instad of a more specific one.")]
internal static bool TryFromStringToColor(string value, out Color result)
{
result = default(Color);
// Parse color specified as hex number
if (value.StartsWith("#", StringComparison.OrdinalIgnoreCase))
{
// Only allow colors in form of #RRGGBB or #RGB
if ((value.Length != 7) && (value.Length != 4))
{
return false;
}
// Expand short version
if (value.Length == 4)
{
char[] newValue = new char[7];
newValue[0] = '#';
newValue[1] = newValue[2] = value[1];
newValue[3] = newValue[4] = value[2];
newValue[5] = newValue[6] = value[3];
value = new string(newValue);
}
}
TypeConverter converter = TypeDescriptor.GetConverter(typeof(Color));
Debug.Assert((converter != null) && (converter.CanConvertFrom(typeof(string))));
// There are no TryConvert APIs on TypeConverter so we have to catch exception.
// In addition to that, invalid conversion just throws System.Exception with misleading message,
// instead of a more specific exception type.
try
{
result = (Color)converter.ConvertFromInvariantString(value);
}
catch (Exception)
{
return false;
}
return true;
}
[SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase",
Justification = "Format names are used in Http headers and are usually specified in lower case")]
internal static string NormalizeImageFormat(string value)
{
value = value.ToLowerInvariant();
switch (value)
{
case "jpeg":
case "jpg":
case "pjpeg":
return "jpeg";
case "png":
case "x-png":
return "png";
case "icon":
case "ico":
return "icon";
}
return value;
}
internal static bool TryFromStringToImageFormat(string value, out ImageFormat result)
{
result = default(ImageFormat);
if (String.IsNullOrEmpty(value))
{
return false;
}
if (value.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
{
value = value.Substring("image/".Length);
}
value = NormalizeImageFormat(value);
TypeConverter converter = TypeDescriptor.GetConverter(typeof(ImageFormat));
Debug.Assert((converter != null) && (converter.CanConvertFrom(typeof(string))));
try
{
result = (ImageFormat)converter.ConvertFromInvariantString(value);
}
catch (NotSupportedException)
{
return false;
}
return true;
}
}
}
|