/// <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.IsNullable());
            Type inputUnderlyingType = Nullable.GetUnderlyingType(inputType);

            generator.EmitCall(inputType.GetMethod("get_Value"));
            if (inputUnderlyingType != outputType)
            {
                Conversion conversion = ConversionFactory.GetConversion(inputUnderlyingType, outputType);
                Contract.Assume(conversion != null);
                conversion.Emit(generator, inputUnderlyingType, outputType, isChecked);
            }
        }
Exemple #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)
        {
            Type       methodType = method.GetParametersNoCopy()[0].ParameterType;
            Conversion conv       = ConversionFactory.GetPreDefinedConversion(inputType, methodType);

            conv.Emit(generator, inputType, methodType, isChecked);
            generator.Emit(OpCodes.Call, method);
            methodType = method.ReturnType;
            conv       = ConversionFactory.GetPreDefinedConversion(methodType, outputType);
            if (conv is FromNullableConversion)
            {
                generator.EmitGetAddress(methodType);
            }
            conv.Emit(generator, methodType, outputType, isChecked);
        }
        /// <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.IsNullable());
            Type inputUnderlyingType  = Nullable.GetUnderlyingType(inputType);
            Type outputUnderlyingType = Nullable.GetUnderlyingType(outputType);
            // 定义变量和标签
            LocalBuilder inputLocal = generator.GetLocal(inputType);
            Label        trueCase   = generator.DefineLabel();
            Label        endConvert = generator.DefineLabel();

            // inputLocal = value;
            generator.Emit(OpCodes.Stloc, inputLocal);
            // if (input.HasValue)
            generator.Emit(OpCodes.Ldloca, inputLocal);
            MethodInfo hasValue = inputType.GetMethod("get_HasValue");

            generator.Emit(OpCodes.Call, hasValue);
            generator.Emit(OpCodes.Brtrue, trueCase);
            // return null
            if (outputUnderlyingType != null)
            {
                // Nullable<T>。
                generator.EmitDefault(outputType);
            }
            else
            {
                // 引用类型。
                generator.Emit(OpCodes.Ldnull);
            }
            generator.Emit(OpCodes.Br, endConvert);
            // else
            generator.MarkLabel(trueCase);
            // (outputType)input.GetValueOrDefault();
            generator.Emit(OpCodes.Ldloca, inputLocal);
            generator.FreeLocal(inputLocal);
            MethodInfo getValueOrDefault = inputType.GetMethod("GetValueOrDefault", Type.EmptyTypes);

            generator.Emit(OpCodes.Call, getValueOrDefault);
            ConversionFactory.GetConversion(inputUnderlyingType, outputUnderlyingType ?? outputType)
            .Emit(generator, inputUnderlyingType, outputUnderlyingType ?? outputType, isChecked);
            if (outputUnderlyingType != null)
            {
                ConstructorInfo ctor = outputType.GetConstructor(new[] { outputUnderlyingType });
                Contract.Assume(ctor != null);
                generator.Emit(OpCodes.Newobj, ctor);
            }
            generator.MarkLabel(endConvert);
        }
Exemple #4
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(outputType.IsNullable());
            var outputUnderlyingType = Nullable.GetUnderlyingType(outputType);

            if (inputType != outputUnderlyingType)
            {
                var conversion = ConversionFactory.GetConversion(inputType, outputUnderlyingType);
                Contract.Assume(conversion != null);
                conversion.Emit(generator, inputType, outputUnderlyingType, isChecked);
            }
            var ctor = outputType.GetConstructor(new[] { outputUnderlyingType });

            Contract.Assume(ctor != null);
            generator.Emit(OpCodes.Newobj, ctor);
        }
Exemple #5
0
            /// <summary>
            /// 更新最优的输入/输出类型。
            /// </summary>
            /// <param name="methodType">类型转换方法的输入/输出类型。</param>
            /// <param name="relation">实际输入类型与方法输入/输出类型间的关系。</param>
            /// <param name="relationJudge">方法输入/输出类型和最优类型间的关系判定。</param>
            /// <param name="bestType">当前的最优类型。</param>
            /// <param name="bestRelation">当前最优类型与实际输入/输出类型间的关系。</param>
            private void UpdateBestType(Type methodType, TypeRelation relation, bool relationJudge,
                                        ref Type bestType, ref TypeRelation bestRelation)
            {
                // 当前选择更差。
                if (relation > bestRelation)
                {
                    return;
                }
                // 当前选择更优,或者当前选择与最佳选择相同,但最佳选择没有类型填充。
                if (relation < bestRelation || bestType == null)
                {
                    bestType     = methodType;
                    bestRelation = relation;
                    bestMethod.Reset();
                    return;
                }
                ConversionType ctype = ConversionFactory.GetStandardConversion(methodType, bestType);

                if (ctype == ConversionType.None)
                {
                    // 找不到类型转换关系,令最佳选择前进至下一级别,并清除类型填充。
                    bestType = null;
                    bestRelation--;
                    bestMethod.Reset();
                    return;
                }
                if (ctype.IsImplicit() == relationJudge)
                {
                    // 当前选择被最优选择包含。
                    if (bestRelation == TypeRelation.Second)
                    {
                        bestType = methodType;
                        bestMethod.Reset();
                    }
                }
                else if (bestRelation == TypeRelation.Thirt)
                {
                    // 当前选择包含最优选择。
                    bestType = methodType;
                    bestMethod.Reset();
                }
            }
Exemple #6
0
            /// <summary>
            /// 查找合适的用户自定义类型转换方法。
            /// </summary>
            /// <returns>合适的用户自定义类型转换方法,如果不存在则为 <c>null</c>。</returns>
            public MethodInfo FindConversion()
            {
                UserConversions convs = GetUserConversions(inputType);

                if (convs != null)
                {
                    Contract.Assume(convs.ConvertToIndex >= 0);
                    for (int i = convs.ConvertToIndex; i < convs.Methods.Length; i++)
                    {
                        UserConversionMethod method = convs.Methods[i];
                        ConversionType       ctype  = ConversionFactory.GetStandardConversion(outputType, method.OutputType);
                        if (ctype == ConversionType.None)
                        {
                            continue;
                        }
                        TypeRelation inputRelation = (method.InputType == inputType) ?
                                                     TypeRelation.Best : TypeRelation.Second;
                        TypeRelation outputRelation = TypeRelation.Best;
                        if (ctype >= ConversionType.ExplicitNumeric)
                        {
                            outputRelation = TypeRelation.Second;
                        }
                        else if (ctype > ConversionType.Identity)
                        {
                            outputRelation = TypeRelation.Thirt;
                        }
                        GetBestConversion(method, inputRelation, outputRelation);
                    }
                }
                convs = GetUserConversions(outputType);
                if (convs != null)
                {
                    for (int i = 0; i < convs.ConvertToIndex; i++)
                    {
                        UserConversionMethod method = convs.Methods[i];
                        ConversionType       ctype  = ConversionFactory.GetStandardConversion(method.InputType, inputType);
                        if (ctype == ConversionType.None)
                        {
                            continue;
                        }
                        TypeRelation outputRelation = (method.OutputType == outputType) ?
                                                      TypeRelation.Best : TypeRelation.Second;
                        TypeRelation inputRelation = TypeRelation.Best;
                        if (ctype >= ConversionType.ExplicitNumeric)
                        {
                            inputRelation = TypeRelation.Second;
                        }
                        else if (ctype > ConversionType.Identity)
                        {
                            inputRelation = TypeRelation.Thirt;
                        }
                        GetBestConversion(method, inputRelation, outputRelation);
                    }
                }
                if (bestMethod.IsUnique)
                {
                    return(bestMethod.Value.Method);
                }
                if (bestMethod.IsAmbig)
                {
                    throw CommonExceptions.AmbiguousUserDefinedConverter(inputType, outputType);
                }
                return(null);
            }