1 using System.Data.Common;
2 using System.Data.SqlClient;
3 using System.Linq.Expressions;
5 using System.Reflection;
7 using System.Runtime.Serialization.Formatters.Binary;
9 using System.Collections.Generic;
10 using System.Collections;
11 using System.Diagnostics.CodeAnalysis;
13 namespace System.Data.Linq {
15 public static class DBConvert {
16 private static Type[] StringArg = new Type[] { typeof(string) };
18 [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Microsoft: Generic parameters are required for strong-typing of the return type.")]
19 public static T ChangeType<T>(object value) {
20 return (T)ChangeType(value, typeof(T));
23 [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Justification = "Microsoft: Cast is dependent on node type and casts do not happen unecessarily in a single code path.")]
24 [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
25 public static object ChangeType(object value, Type type) {
29 Type toType = System.Data.Linq.SqlClient.TypeSystem.GetNonNullableType(type);
30 Type fromType = value.GetType();
31 if (toType.IsAssignableFrom(fromType))
34 if (toType == typeof(Binary)) {
35 if (fromType == typeof(byte[])) {
36 return new Binary((byte[])value);
38 else if (fromType == typeof(Guid)) {
39 return new Binary(((Guid)value).ToByteArray());
42 BinaryFormatter formatter = new BinaryFormatter();
44 using (MemoryStream stream = new MemoryStream()) {
45 formatter.Serialize(stream, value);
46 streamArray = stream.ToArray();
48 return new Binary(streamArray);
51 else if (toType == typeof(byte[])) {
52 if (fromType == typeof(Binary)) {
53 return ((Binary)value).ToArray();
55 else if (fromType == typeof(Guid)) {
56 return ((Guid)value).ToByteArray();
59 BinaryFormatter formatter = new BinaryFormatter();
61 using (MemoryStream stream = new MemoryStream()) {
62 formatter.Serialize(stream, value);
63 returnValue = stream.ToArray();
68 else if (fromType == typeof(byte[])) {
69 if (toType == typeof(Guid)) {
70 return new Guid((byte[])value);
73 BinaryFormatter formatter = new BinaryFormatter();
75 using (MemoryStream stream = new MemoryStream((byte[])value)) {
76 returnValue = ChangeType(formatter.Deserialize(stream), toType);
81 else if (fromType == typeof(Binary)) {
82 if (toType == typeof(Guid)) {
83 return new Guid(((Binary)value).ToArray());
86 BinaryFormatter formatter = new BinaryFormatter();
87 using (MemoryStream stream = new MemoryStream(((Binary)value).ToArray(), false)) {
88 return ChangeType(formatter.Deserialize(stream), toType);
92 else if (toType.IsEnum) {
93 if (fromType == typeof(string)) {
94 string text = ((string)value).Trim();
95 return Enum.Parse(toType, text);
98 return Enum.ToObject(toType, Convert.ChangeType(value, Enum.GetUnderlyingType(toType), Globalization.CultureInfo.InvariantCulture));
101 else if (fromType.IsEnum) {
102 if (toType == typeof(string)) {
103 return Enum.GetName(fromType, value);
106 return Convert.ChangeType(Convert.ChangeType(value,
107 Enum.GetUnderlyingType(fromType),
108 Globalization.CultureInfo.InvariantCulture),
110 Globalization.CultureInfo.InvariantCulture);
113 else if (toType == typeof(TimeSpan)) {
114 if (fromType == typeof(string)) {
115 return TimeSpan.Parse(value.ToString(), Globalization.CultureInfo.InvariantCulture);
117 else if (fromType == typeof(DateTime)) {
118 return DateTime.Parse(value.ToString(), Globalization.CultureInfo.InvariantCulture).TimeOfDay;
120 else if (fromType == typeof(DateTimeOffset)) {
121 return DateTimeOffset.Parse(value.ToString(), Globalization.CultureInfo.InvariantCulture).TimeOfDay;
124 return new TimeSpan((long)Convert.ChangeType(value, typeof(long), Globalization.CultureInfo.InvariantCulture));
127 else if (fromType == typeof(TimeSpan)) {
128 if (toType == typeof(string)) {
129 return ((TimeSpan)value).ToString("", Globalization.CultureInfo.InvariantCulture);
131 else if (toType == typeof(DateTime)) {
132 DateTime dt = new DateTime();
133 return dt.Add((TimeSpan)value);
135 else if (toType == typeof(DateTimeOffset)) {
136 DateTimeOffset dto = new DateTimeOffset();
137 return dto.Add((TimeSpan)value);
140 return Convert.ChangeType(((TimeSpan)value).Ticks, toType, Globalization.CultureInfo.InvariantCulture);
143 else if (toType == typeof(DateTime) && fromType == typeof(DateTimeOffset)) {
144 return ((DateTimeOffset)value).DateTime;
146 else if (toType == typeof(DateTimeOffset) && fromType == typeof(DateTime)) {
147 return new DateTimeOffset((DateTime)value);
149 else if (toType == typeof(string) && !(typeof(IConvertible).IsAssignableFrom(fromType))) {
150 if (fromType == typeof(char[])) {
151 return new String((char[])value);
154 return value.ToString();
157 else if (fromType == typeof(string)) {
158 if (toType == typeof(Guid)) {
159 return new Guid((string)value);
161 else if (toType == typeof(char[])) {
162 return ((String)value).ToCharArray();
164 else if (toType == typeof(System.Xml.Linq.XDocument) && (string)value == string.Empty) {
165 return new System.Xml.Linq.XDocument();
167 else if (!(typeof(IConvertible).IsAssignableFrom(toType)) &&
168 (mi = toType.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, StringArg, null)) != null) {
170 return SecurityUtils.MethodInfoInvoke(mi, null, new object[] { value });
172 catch (TargetInvocationException t) {
173 throw t.GetBaseException();
177 return Convert.ChangeType(value, toType, Globalization.CultureInfo.InvariantCulture);
180 else if (toType.IsGenericType && toType.GetGenericTypeDefinition() == typeof(IQueryable<>)
181 && typeof(IEnumerable<>).MakeGenericType(toType.GetGenericArguments()[0]).IsAssignableFrom(fromType)
183 return Queryable.AsQueryable((IEnumerable)value);
187 return Convert.ChangeType(value, toType, Globalization.CultureInfo.InvariantCulture);
188 } catch (InvalidCastException) {
189 throw Error.CouldNotConvert(fromType, toType);