Ejemplo n.º 1
0
        /// <summary>
        /// 返回的将对象从 <paramref name="inputType"/> 类型转换为 <paramref name="outputType"/>
        /// 类型的用户自定义类型转换。
        /// </summary>
        /// <param name="inputType">要转换的对象的类型。</param>
        /// <param name="outputType">要将输入对象转换到的类型。</param>
        /// <returns>将对象从 <paramref name="inputType"/> 类型转换为 <paramref name="outputType"/>
        /// 类型的用户自定义类型转换,如果不存在则为 <c>null</c>。</returns>
        private static Conversion GetUserDefinedConversion(Type inputType, Type outputType)
        {
            Contract.Requires(inputType != null && outputType != null &&
                              inputType != typeof(void) && outputType != typeof(void));
            // 判断可空类型。
            Type       inputUnderlyingType  = inputType.GetNonNullableType();
            Type       outputUnderlyingType = outputType.GetNonNullableType();
            MethodInfo method = UserConversionCache.GetConversion(inputUnderlyingType, outputUnderlyingType);

            if (method == null)
            {
                return(null);
            }
            Conversion conversion = new UserConversion(method);
            // 存入缓存。
            Type methodInputType   = method.GetParametersNoCopy()[0].ParameterType;
            Tuple <Type, Type> key = new Tuple <Type, Type>(inputType, outputType);

            if (inputType != methodInputType || outputType != method.ReturnType)
            {
                conversion = userDefinedConverers.GetOrAdd(new Tuple <Type, Type>(methodInputType, method.ReturnType),
                                                           conversion);
            }
            if (inputUnderlyingType != inputType || outputUnderlyingType != outputType)
            {
                userDefinedConverers.TryAdd(new Tuple <Type, Type>(inputUnderlyingType, outputUnderlyingType), conversion);
            }
            if (inputUnderlyingType == inputType || !methodInputType.IsValueType || methodInputType.IsNullable())
            {
                return(userDefinedConverers.GetOrAdd(key, conversion));
            }
            // 需要将输入的 Nullable<T> 解包。
            if (outputUnderlyingType != outputType || !outputType.IsValueType)
            {
                // outputType 可以为 null(引用类型或 Nullable<T>)。
                return(userDefinedConverers.GetOrAdd(key, BetweenNullableConversion.UserDefined));
            }
            return(userDefinedConverers.GetOrAdd(key, FromNullableConversion.UserDefined));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 写入类型转换的 IL 指令。
        /// </summary>
        /// <param name="generator">IL 的指令生成器。</param>
        /// <param name="inputType">要转换的对象的类型。</param>
        /// <param name="outputType">要将输入对象转换到的类型。</param>
        /// <param name="isChecked">是否执行溢出检查。</param>
        public override void Emit(ILGenerator generator, Type inputType, Type outputType, bool isChecked)
        {
            Contract.Assume((inputType == typeof(decimal) && outputType.IsNumeric()) ||
                            (outputType == typeof(decimal) && inputType.IsNumeric()));
            MethodInfo method;

            if (inputType == typeof(decimal))
            {
                if (outputType.IsEnum)
                {
                    outputType = Enum.GetUnderlyingType(outputType);
                }
                method = UserConversionCache.GetConversionTo(inputType, outputType);
            }
            else
            {
                if (inputType.IsEnum)
                {
                    inputType = Enum.GetUnderlyingType(inputType);
                }
                method = UserConversionCache.GetConversionFrom(outputType, inputType);
            }
            generator.EmitCall(method);
        }