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 } |
