using System; using System.Reflection; using BLToolkit.Reflection; namespace BLToolkit.Common { /// /// Converts a base data type to another base data type. /// /// Source data type. /// Destination data type. public static class Convert { /// /// Represents a method that converts an object from one type to another type. /// /// A value to convert to the target type. /// The that represents the converted . public delegate T ConvertMethod(P p); /// Converts an array of one type to an array of another type. /// An array of the target type containing the converted elements from the source array. /// The one-dimensional, zero-based to convert to a target type. /// array is null.-or-converter is null. public static T[] FromArray(P[] src) { // Note that type parameters are in reverse order. // return Array.ConvertAll(src, (Converter)((object)From)); } /// /// Converter instance. /// public static ConvertMethod From = GetConverter(); /// /// Initializes converter instance. /// ///Converter instance. public static ConvertMethod GetConverter() { Type from = typeof(P); Type to = typeof(T); // Convert to the same type. // if (to == from) return (ConvertMethod)(object)(Convert.ConvertMethod)SameType; if (from.IsEnum) from = Enum.GetUnderlyingType(from); if (to.IsEnum) to = Enum.GetUnderlyingType(to); if (TypeHelper.IsSameOrParent(to, from)) return Assignable; string methodName; if (TypeHelper.IsNullable(to)) methodName = "ToNullable" + to.GetGenericArguments()[0].Name; else if (to.IsArray) methodName = "To" + to.GetElementType().Name + "Array"; else methodName = "To" + to.Name; MethodInfo mi = typeof(Convert).GetMethod(methodName, BindingFlags.Public | BindingFlags.Static | BindingFlags.ExactBinding, null, new Type[] {from}, null) ?? FindTypeCastOperator(to) ?? FindTypeCastOperator(from); if (mi == null && TypeHelper.IsNullable(to)) { // To-nullable conversion. // We have to use reflection to enforce some constraints. // Type toType = to.GetGenericArguments()[0]; Type fromType = TypeHelper.IsNullable(from)? from.GetGenericArguments()[0]: from; methodName = TypeHelper.IsNullable(from) ? "FromNullable" : "From"; mi = typeof(NullableConvert<,>) .MakeGenericType(toType, fromType) .GetMethod(methodName, BindingFlags.Public | BindingFlags.Static); } if (mi != null) return (ConvertMethod)Delegate.CreateDelegate(typeof(ConvertMethod), mi); return Default; } private static MethodInfo FindTypeCastOperator(Type t) { foreach (MethodInfo mi in t.GetMethods(BindingFlags.Public | BindingFlags.Static)) { if (mi.IsSpecialName && mi.ReturnType == typeof(T) && (mi.Name == "op_Implicit" || mi.Name == "op_Explicit")) { ParameterInfo[] parameters = mi.GetParameters(); if (1 == parameters.Length && parameters[0].ParameterType == typeof(P)) return mi; } } return null; } private static P SameType (P p) { return p; } private static T Assignable(P p) { return (T)(object)p; } private static T Default (P p) { return (T)System.Convert.ChangeType(p, typeof(T)); } } /// /// Converts a base data type to another base data type. /// /// Destination data type. public static class ConvertTo { /// Returns an whose value is equivalent to the specified value. /// The that represents the converted . /// A value to convert to the target type. public static T From

(P p) { return Convert.From(p); } } internal static class NullableConvert where T: struct where P: struct { public static T? FromNullable(P? p) { return p.HasValue? From(p.Value): null; } public static T? From(P p) { return Convert.From(p); } } }