Mercurial > pub > bltoolkit
comparison Source/Common/ConvertT.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f990fcb411a9 |
---|---|
1 using System; | |
2 using System.Reflection; | |
3 using System.Threading; | |
4 | |
5 namespace BLToolkit.Common | |
6 { | |
7 using Reflection; | |
8 | |
9 /// <summary> | |
10 /// Converts a base data type to another base data type. | |
11 /// </summary> | |
12 /// <typeparam name="T">Destination data type.</typeparam> | |
13 /// <typeparam name="P">Source data type.</typeparam> | |
14 public static class Convert<T,P> | |
15 { | |
16 /// <summary> | |
17 /// Represents a method that converts an object from one type to another type. | |
18 /// </summary> | |
19 /// <param name="p">A value to convert to the target type.</param> | |
20 /// <returns>The <typeparamref name="T"/> that represents the converted <paramref name="p"/>.</returns> | |
21 public delegate T ConvertMethod(P p); | |
22 | |
23 /// <summary>Converts an array of one type to an array of another type.</summary> | |
24 /// <returns>An array of the target type containing the converted elements from the source array.</returns> | |
25 /// <param name="src">The one-dimensional, zero-based <see cref="T:System.Array"></see> to convert to a target type.</param> | |
26 /// <exception cref="T:System.ArgumentNullException">array is null.-or-converter is null.</exception> | |
27 public static T[] FromArray(P[] src) | |
28 { | |
29 var arr = new T[src.Length]; | |
30 | |
31 for (var i = 0; i < arr.Length; i++) | |
32 arr[i] = From(src[i]); | |
33 | |
34 return arr; | |
35 } | |
36 | |
37 ///<summary> | |
38 /// Converter instance. | |
39 ///</summary> | |
40 public static ConvertMethod From = GetConverter(); | |
41 | |
42 ///<summary> | |
43 /// Initializes converter instance. | |
44 ///</summary> | |
45 ///<returns>Converter instance.</returns> | |
46 public static ConvertMethod GetConverter() | |
47 { | |
48 var from = typeof(P); | |
49 var to = typeof(T); | |
50 | |
51 // Convert to the same type. | |
52 // | |
53 if (to == from) | |
54 return (ConvertMethod)(object)(Convert<P,P>.ConvertMethod)SameType; | |
55 | |
56 if (from.IsEnum) | |
57 from = Enum.GetUnderlyingType(from); | |
58 | |
59 if (to.IsEnum) | |
60 to = Enum.GetUnderlyingType(to); | |
61 | |
62 if (TypeHelper.IsSameOrParent(to, from)) | |
63 return Assignable; | |
64 | |
65 string methodName; | |
66 | |
67 if (TypeHelper.IsNullable(to)) | |
68 methodName = "ToNullable" + to.GetGenericArguments()[0].Name; | |
69 else if (to.IsArray) | |
70 methodName = "To" + to.GetElementType().Name + "Array"; | |
71 else if (to.Name == "Binary") | |
72 methodName = "ToLinq" + to.Name; | |
73 else | |
74 methodName = "To" + to.Name; | |
75 | |
76 var mi = typeof(Convert).GetMethod(methodName, | |
77 BindingFlags.Public | BindingFlags.Static | BindingFlags.ExactBinding, | |
78 null, new[] { from }, null) ?? FindTypeCastOperator(to) ?? FindTypeCastOperator(from); | |
79 | |
80 if (mi == null && TypeHelper.IsNullable(to)) | |
81 { | |
82 // To-nullable conversion. | |
83 // We have to use reflection to enforce some constraints. | |
84 // | |
85 var toType = to.GetGenericArguments()[0]; | |
86 var fromType = TypeHelper.IsNullable(from)? from.GetGenericArguments()[0]: from; | |
87 | |
88 methodName = TypeHelper.IsNullable(from) ? "FromNullable" : "From"; | |
89 | |
90 mi = typeof(NullableConvert<,>) | |
91 .MakeGenericType(toType, fromType) | |
92 .GetMethod(methodName, BindingFlags.Public | BindingFlags.Static); | |
93 } | |
94 | |
95 if (mi != null) | |
96 return (ConvertMethod)Delegate.CreateDelegate(typeof(ConvertMethod), mi); | |
97 | |
98 return Default; | |
99 } | |
100 | |
101 private static MethodInfo FindTypeCastOperator(Type t) | |
102 { | |
103 foreach (var mi in t.GetMethods(BindingFlags.Public | BindingFlags.Static)) | |
104 { | |
105 if (mi.IsSpecialName && mi.ReturnType == typeof(T) && (mi.Name == "op_Implicit" || mi.Name == "op_Explicit")) | |
106 { | |
107 var parameters = mi.GetParameters(); | |
108 | |
109 if (1 == parameters.Length && parameters[0].ParameterType == typeof(P)) | |
110 return mi; | |
111 } | |
112 } | |
113 | |
114 return null; | |
115 } | |
116 | |
117 private static P SameType (P p) { return p; } | |
118 private static T Assignable(P p) { return (T)(object)p; } | |
119 private static T Default (P p) { return (T)System.Convert.ChangeType(p, typeof(T), Thread.CurrentThread.CurrentCulture); } | |
120 } | |
121 | |
122 /// <summary> | |
123 /// Converts a base data type to another base data type. | |
124 /// </summary> | |
125 /// <typeparam name="T">Destination data type.</typeparam> | |
126 public static class ConvertTo<T> | |
127 { | |
128 /// <summary>Returns an <typeparamref name="T"/> whose value is equivalent to the specified value.</summary> | |
129 /// <returns>The <typeparamref name="T"/> that represents the converted <paramref name="p"/>.</returns> | |
130 /// <param name="p">A value to convert to the target type.</param> | |
131 public static T From<P>(P p) | |
132 { | |
133 return Convert<T,P>.From(p); | |
134 } | |
135 } | |
136 | |
137 internal static class NullableConvert<T,P> | |
138 where T: struct | |
139 where P: struct | |
140 { | |
141 public static T? FromNullable(P? p) | |
142 { | |
143 return p.HasValue? From(p.Value): null; | |
144 } | |
145 | |
146 public static T? From(P p) | |
147 { | |
148 return Convert<T,P>.From(p); | |
149 } | |
150 } | |
151 } |