Ejemplo n.º 1
0
        /// <summary>
        /// 构造类型转换器。
        /// </summary>
        /// <param name="conversion">使用的类型转换。</param>
        /// <param name="inputType">要转换的对象的类型。</param>
        /// <param name="outputType">要将输入对象转换到的类型。</param>
        /// <param name="isChecked">是否执行溢出检查。</param>
        /// <param name="buildGeneric"><c>true</c> 表示需要生成泛型类型转换委托;<c>false</c>
        /// 表示需要生成非泛型的类型转换委托。</param>
        /// <returns>将对象从 <paramref name="inputType"/> 类型转换为 <paramref name="outputType"/> 类型的转换器。</returns>
        private static Delegate BuildConverter(Conversion conversion, Type inputType, Type outputType, bool isChecked,
                                               bool buildGeneric)
        {
            Contract.Requires(conversion != null && inputType != null && outputType != null);
            Contract.Ensures(Contract.Result <Delegate>() != null);
            var method = new DynamicMethod("Converter", buildGeneric ? outputType : typeof(object),
                                           new[] { buildGeneric?inputType: typeof(object) }, true);
            var il            = method.GetILGenerator();
            var passByAddress = conversion is FromNullableConversion;

            if (passByAddress && (buildGeneric || !inputType.IsValueType))
            {
                il.Emit(OpCodes.Ldarga_S, (byte)0);
            }
            else
            {
                il.Emit(OpCodes.Ldarg_0);
            }
            if (buildGeneric)
            {
                conversion.Emit(il, inputType, outputType, isChecked);
                il.Emit(OpCodes.Ret);
                return(method.CreateDelegate(typeof(Converter <,>).MakeGenericType(inputType, outputType)));
            }
            // 从 object 拆箱得到值类型。
            ConversionFactory.GetPreDefinedConversionNotVoid(typeof(object), inputType).Emit(il, typeof(object), inputType, isChecked);
            if (passByAddress)
            {
                il.EmitGetAddress(inputType);
            }
            conversion.Emit(il, inputType, outputType, isChecked);
            // 值类型装箱为 object。
            if (outputType.IsValueType)
            {
                il.Emit(OpCodes.Box, outputType);
            }
            il.Emit(OpCodes.Ret);
            return(method.CreateDelegate(typeof(Converter <object, object>)));
        }