Example #1
0
 /// <summary>
 /// 根据给定的用户定义转换获取最合适的转换。
 /// </summary>
 /// <param name="method">要测试的用户定义转换。</param>
 /// <param name="exactSource">当前最合适的源类型。</param>
 /// <param name="exactTarget">当前最合适的目标类型。</param>
 /// <param name="uniqueMethod">最合适的转换。</param>
 private static void GetBestConversion(ConversionMethod method, ref Type exactSource, ref Type exactTarget,
                                       UniqueValue <ConversionMethod> uniqueMethod)
 {
     if (exactSource != method.SourceType)
     {
         if (exactSource != null && method.SourceType.IsAssignableFrom(exactSource))
         {
             return;
         }
         else
         {
             exactSource = method.SourceType;
             uniqueMethod.Reset();
         }
     }
     if (exactTarget != method.TargetType)
     {
         if (exactTarget != null && exactTarget.IsAssignableFrom(method.TargetType))
         {
             return;
         }
         else
         {
             exactTarget = method.TargetType;
             uniqueMethod.Reset();
         }
     }
     uniqueMethod.Value = method;
 }
Example #2
0
        /// <summary>
        /// 返回从源类型到目标类型的用户定义的显式转换方法。
        /// 该转换方法的参数与源类型和目标类型并不一定完全相同,但保证存在标准显式转换。
        /// </summary>
        /// <param name="sourceType">要获取用户定义的转换方法的源类型。</param>
        /// <param name="targetType">要获取用户定义的转换方法的目标类型。</param>
        /// <returns>如果存在从源类型到目标类型的用户定义的显式转换方法,则返回该方法;
        /// 否则返回 <c>null</c>。</returns>
        public static ConversionMethod GetExplicitConversion(Type sourceType, Type targetType)
        {
            Type exactSource = null, exactTarget = null;
            UniqueValue <ConversionMethod> method = new UniqueValue <ConversionMethod>();
            Conversion conv = GetTypeConversions(sourceType.GetNonNullableType());

            for (int i = conv.ConvertToIndex; i < conv.Methods.Length; i++)
            {
                ConversionMethod m = conv.Methods[i];
                if (targetType.IsStandardExplicitFrom(m.TargetType))
                {
                    GetBestConversion(m, ref exactSource, ref exactTarget, method);
                }
            }
            conv = GetTypeConversions(targetType.GetNonNullableType());
            for (int i = Conversion.ConvertFromIndex; i < conv.ConvertToIndex; i++)
            {
                ConversionMethod m = conv.Methods[i];
                if (m.SourceType.IsStandardExplicitFrom(sourceType))
                {
                    GetBestConversion(m, ref exactSource, ref exactTarget, method);
                }
            }
            if (method.IsUnique)
            {
                return(method.Value);
            }
            return(null);
        }
Example #3
0
        /// <summary>
        /// 返回指定类型的对象,其值等效于指定对象。参数提供区域性特定的格式设置信息。
        /// 只对允许进行隐式类型转换。
        /// </summary>
        /// <param name="value">要转换的对象。</param>
        /// <param name="conversionType">要返回的对象的类型。</param>
        /// <param name="provider">一个提供区域性特定的格式设置信息的对象。</param>
        /// <returns>一个对象,其类型为 <paramref name="conversionType"/>,
        /// 并且其值等效于 <paramref name="value"/>。</returns>
        internal static object ImplicitChangeType(object value, Type conversionType, IFormatProvider provider)
        {
            Type nonNullableType;

            if (BasicChangeType(ref value, conversionType, out nonNullableType))
            {
                return(value);
            }
            Type type = value.GetType();
            // 尝试标准隐式类型转换。
            bool   success;
            object result = StandardImplicitChangeType(value, type, nonNullableType, provider, out success);

            if (success)
            {
                return(result);
            }
            // 对隐式类型转换运算符进行判断。
            ConversionMethod method = ConversionCache.GetImplicitConversion(type, conversionType);

            if (method != null)
            {
                value = MethodInfo.GetMethodFromHandle(method.Method).Invoke(null, new object[] { value });
                if (value != null)
                {
                    type = value.GetType();
                    if (type != nonNullableType)
                    {
                        // 处理用户定义隐式类型转换之后的标准隐式类型转换。
                        value = StandardImplicitChangeType(value, type, nonNullableType, provider, out success);
                    }
                }
                return(value);
            }
            throw CommonExceptions.ConvertInvalidValue(value, conversionType);
        }
Example #4
0
        /// <summary>
        /// 返回指定类型的对象,其值等效于指定对象。参数提供区域性特定的格式设置信息。
        /// 支持可空类型、枚举和用户自定义类型转换。
        /// </summary>
        /// <param name="value">要转换的对象。</param>
        /// <param name="conversionType">要返回的对象的类型。</param>
        /// <param name="provider">一个提供区域性特定的格式设置信息的对象。</param>
        /// <returns>一个对象,其类型为 <paramref name="conversionType"/>,
        /// 并且其值等效于 <paramref name="value"/>。</returns>
        /// <overloads>
        /// <summary>
        /// 返回指定类型的对象,其值等效于指定对象。支持可空类型、枚举和用户自定义类型转换。
        /// </summary>
        /// </overloads>
        public static object ChangeType(object value, Type conversionType, IFormatProvider provider)
        {
            Type nonNullableType;

            if (BasicChangeType(ref value, conversionType, out nonNullableType))
            {
                return(value);
            }
            Type type = value.GetType();

            // 尝试显示枚举转换。
            if (conversionType.IsEnumExplicitFrom(type))
            {
                if (conversionType.IsEnum)
                {
                    // Enum.ToObject 不支持 char, float, double 和 decimal。
                    switch (Type.GetTypeCode(type))
                    {
                    case TypeCode.Char:
                        value = (ushort)(char)value;
                        break;

                    case TypeCode.Single:
                        value = (long)(float)value;
                        break;

                    case TypeCode.Double:
                        value = (long)(double)value;
                        break;

                    case TypeCode.Decimal:
                        value = (long)(decimal)value;
                        break;
                    }
                    return(Enum.ToObject(conversionType, value));
                }
                return(Convert.ChangeType(value, conversionType, provider));
            }
            // 尝试标准显式类型转换。
            bool   success;
            object result = StandardExplicitChangeType(value, type, nonNullableType, provider, out success);

            if (success)
            {
                return(result);
            }
            // 对显式类型转换运算符进行判断。
            ConversionMethod method = ConversionCache.GetExplicitConversion(type, conversionType);

            if (method != null)
            {
                value = MethodBase.GetMethodFromHandle(method.Method).Invoke(null, new [] { value });
                if (value != null)
                {
                    type = value.GetType();
                    if (type != nonNullableType)
                    {
                        // 处理用户定义显式类型转换之后的标准显式类型转换。
                        value = StandardExplicitChangeType(value, type, nonNullableType, provider, out success);
                    }
                }
                return(value);
            }
            // 尝试其他支持的转换。
            return(Convert.ChangeType(value, conversionType, provider));
        }
Example #5
0
        /// <summary>
        /// 返回指定类型中用户定义的转换方法。
        /// </summary>
        /// <param name="type">要获取类型转换方法的类型。</param>
        /// <returns>指定类型中用户定义的转换方法。</returns>
        private static Conversion GetTypeConversions(Type type)
        {
            TypeCode typeCode = Type.GetTypeCode(type);

            if (typeCode != TypeCode.Object && typeCode != TypeCode.Decimal)
            {
                // 其余内置类型都不包含类型转换运算符。
                return(Conversion.Empty);
            }
            return(Conversions.GetOrAdd(type, t =>
            {
                Conversion conv = new Conversion();
                List <ConversionMethod> cList = new List <ConversionMethod>();
                MethodInfo[] methods = t.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
                for (int i = 0; i < methods.Length; i++)
                {
                    MethodInfo m = methods[i];
                    bool opImplicit = m.Name.Equals(ImplicitConversionName, StringComparison.Ordinal);
                    // 如果 opImplicit 已经为 true,则不需要再次进行方法名称的比较。
                    bool opExplicit = opImplicit ? false : m.Name.Equals(ExplicitConviersionName, StringComparison.Ordinal);
                    if (opImplicit || opExplicit)
                    {
                        if (m.ReturnType == type)
                        {
                            // 转换自其它类型。
                            int index = conv.ImplicitConvertFromIndex;
                            if (opExplicit)
                            {
                                index = Conversion.ConvertFromIndex;
                                conv.ImplicitConvertFromIndex++;
                            }
                            conv.ConvertToIndex++;
                            conv.ImplicitConvertToIndex++;
                            cList.Insert(index, new ConversionMethod(m.GetParameters()[0].ParameterType, t, m));
                        }
                        else
                        {
                            // 转换到其它类型。
                            int index = conv.ImplicitConvertToIndex;
                            if (opExplicit)
                            {
                                index = conv.ConvertToIndex;
                                conv.ImplicitConvertToIndex++;
                            }
                            cList.Insert(index, new ConversionMethod(t, m.ReturnType, m));
                        }
                    }
                }
                // 如果子类的类型转换运算符与基类完全相同,则为 true;否则为 false。
                bool sameWithBase = (cList.Count == 0);
                // 基类转换为其它类型的运算符是可以由子类继承的。
                if (type.IsClass)
                {
                    Conversion baseConv = GetTypeConversions(type.BaseType);
                    for (int i = baseConv.ConvertToIndex; i < baseConv.Methods.Length; i++)
                    {
                        ConversionMethod m = baseConv.Methods[i];
                        bool contains = false;
                        for (int j = conv.ConvertToIndex; j < cList.Count; j++)
                        {
                            if (cList[j].TargetType == m.TargetType)
                            {
                                sameWithBase = false;
                                contains = true;
                                break;
                            }
                        }
                        if (!contains)
                        {
                            if (i >= baseConv.ImplicitConvertToIndex)
                            {
                                cList.Insert(conv.ImplicitConvertToIndex, m);
                            }
                            else
                            {
                                cList.Insert(conv.ConvertToIndex, m);
                                conv.ImplicitConvertToIndex++;
                            }
                        }
                    }
                    if (sameWithBase)
                    {
                        // 这时候可以略微节约内存。
                        return baseConv;
                    }
                }
                if (sameWithBase)
                {
                    // 这时候可以略微节约内存。
                    return Conversion.Empty;
                }
                conv.Methods = cList.ToArray();
                return conv;
            }));
        }