/// <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)); }
/// <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); }