/// <summary> /// 确定当前 <see cref="Type"/> 的实例是否可以从 <paramref name="fromType"/> 的实例显式类型转换得到。 /// 这里仅考虑预定义的显式类型转换,不考虑由 <c>implicit</c> 运算符和 <c>explicit</c> 运算符指定的转换。 /// </summary> /// <param name="type">当前类型。</param> /// <param name="fromType">要判断能否显式类型转换得到的类型。</param> /// <returns>如果当前 <see cref="Type"/> 的实例是否可以从 <paramref name="fromType"/> /// 的实例显式类型转换得到,则为 <c>true</c>;否则为 <c>false</c>。</returns> /// <exception cref="ArgumentNullException"><paramref name="type"/> 为 <c>null</c>。</exception> /// <exception cref="ArgumentNullException"><paramref name="fromType"/> 为 <c>null</c>。</exception> /// <remarks> /// 判断类型间能否进行显式类型转换的算法来自于 《CSharp Language Specification》v5.0 /// 的第 6.1 节。</remarks> /// <example> /// 下面是 <see cref="IsExplicitFrom"/> 方法的一些实例。 /// <code> /// Console.WriteLine(typeof(uint).IsExplicitFrom(typeof(object))); // True /// Console.WriteLine(typeof(short).IsExplicitFrom(typeof(int))); // True /// Console.WriteLine(typeof(int).IsExplicitFrom(typeof(long?))); // True /// </code> /// </example> /// <seealso href="http://www.cnblogs.com/cyjb/archive/p/TypeAssignableFrom.html"> /// 《C# 判断类型间能否隐式或强制类型转换,以及开放泛型类型转换》</seealso> public static bool IsExplicitFrom(this Type type, Type fromType) { CommonExceptions.CheckArgumentNull(type, "type"); CommonExceptions.CheckArgumentNull(fromType, "fromType"); Contract.EndContractBlock(); Conversion conversion = ConversionFactory.GetPreDefinedConversion(fromType, type); return(conversion != null && conversion.ConversionType != ConversionType.None); }
/// <summary> /// 确定当前 <see cref="Type"/> 的实例是否可以从 <paramref name="fromType"/> 的实例隐式类型转换得到。 /// 这里仅考虑预定义的隐式类型转换,不考虑由 <c>implicit</c> 运算符指定的转换。 /// </summary> /// <param name="type">当前类型。</param> /// <param name="fromType">要判断能否隐式类型转换得到的类型。</param> /// <returns>如果当前 <see cref="Type"/> 的实例是否可以从 <paramref name="fromType"/> /// 的实例隐式类型转换得到,则为 <c>true</c>;否则为 <c>false</c>。</returns> /// <exception cref="ArgumentNullException"><paramref name="type"/> 为 <c>null</c>。</exception> /// <exception cref="ArgumentNullException"><paramref name="fromType"/> 为 <c>null</c>。</exception> /// <remarks> /// 判断类型间能否进行隐式类型转换的算法来自于 《CSharp Language Specification》v5.0 /// 的第 6.1 节。</remarks> /// <example> /// 下面是 <see cref="IsImplicitFrom"/> 方法与 <see cref="Type.IsAssignableFrom"/> 方法的一些对比。 /// <code> /// Console.WriteLine(typeof(object).IsAssignableFrom(typeof(uint))); // True /// Console.WriteLine(typeof(object).IsImplicitFrom(typeof(uint))); // True /// Console.WriteLine(typeof(int).IsAssignableFrom(typeof(short))); // False /// Console.WriteLine(typeof(int).IsImplicitFrom(typeof(short))); // True /// Console.WriteLine(typeof(long?).IsAssignableFrom(typeof(int?))); // False /// Console.WriteLine(typeof(long?).IsImplicitFrom(typeof(int?))); // True /// </code> /// </example> /// <seealso href="http://www.cnblogs.com/cyjb/archive/p/TypeAssignableFrom.html"> /// 《C# 判断类型间能否隐式或强制类型转换,以及开放泛型类型转换》</seealso> public static bool IsImplicitFrom(this Type type, Type fromType) { CommonExceptions.CheckArgumentNull(type, nameof(type)); CommonExceptions.CheckArgumentNull(fromType, nameof(fromType)); Contract.EndContractBlock(); var conversion = ConversionFactory.GetPreDefinedConversion(fromType, type); return(conversion != null && conversion.ConversionType.IsImplicit()); }
/// <summary> /// 确定当前 <see cref="Type"/> 的实例是否可以从 <paramref name="fromType"/> 的实例显式类型转换得到。 /// 这里仅考虑预定义的显式类型转换,不考虑由 <c>implicit</c> 运算符和 <c>explicit</c> 运算符指定的转换。 /// </summary> /// <param name="type">当前类型。</param> /// <param name="fromType">要判断能否显式类型转换得到的类型。</param> /// <returns>如果当前 <see cref="Type"/> 的实例是否可以从 <paramref name="fromType"/> /// 的实例显式类型转换得到,则为 <c>true</c>;否则为 <c>false</c>。</returns> /// <exception cref="ArgumentNullException"><paramref name="type"/> 为 <c>null</c>。</exception> /// <exception cref="ArgumentNullException"><paramref name="fromType"/> 为 <c>null</c>。</exception> /// <remarks> /// 判断类型间能否进行显式类型转换的算法来自于 《CSharp Language Specification》v5.0 /// 的第 6.1 节。</remarks> /// <example> /// 下面是 <see cref="IsImplicitFrom"/> 方法的一些实例。 /// <code> /// Console.WriteLine(typeof(uint).IsExplicitFrom(typeof(object))); // True /// Console.WriteLine(typeof(short).IsExplicitFrom(typeof(int))); // True /// Console.WriteLine(typeof(int).IsExplicitFrom(typeof(long?))); // True /// </code> /// </example> /// <seealso href="http://www.cnblogs.com/cyjb/archive/p/TypeAssignableFrom.html"> /// 《C# 判断类型间能否隐式或强制类型转换,以及开放泛型类型转换》</seealso> public static bool IsExplicitFrom(this Type type, Type fromType) { if (type == null) { throw CommonExceptions.ArgumentNull("type"); } if (fromType == null) { throw CommonExceptions.ArgumentNull("otherType"); } Contract.EndContractBlock(); Conversion conversion = ConversionFactory.GetPreDefinedConversion(fromType, type); return(conversion != null && conversion.ConversionType != ConversionType.None); }
/// <summary> /// 获取转换类型的指令生成器,能够将栈顶的对象从 <paramref name="inputType"/> 转换为 /// <paramref name="outputType"/>。 /// </summary> /// <param name="il">IL 指令生成器。</param> /// <param name="inputType">要转换的对象的类型。</param> /// <param name="outputType">要将输入对象转换到的类型。</param> /// <param name="conversionType">类型转换类型的限制。</param> /// <returns>类型转换的指令生成器,如果不能进行类型转换则返回 <c>null</c>。</returns> internal static Converter GetConversion(this ILGenerator il, Type inputType, Type outputType, ConversionType conversionType) { Contract.Requires(il != null && inputType != null && outputType != null); Contract.Requires(conversionType == ConversionType.Implicit || conversionType == ConversionType.Explicit || conversionType == ConversionType.UserDefined); Conversion conversion = conversionType == ConversionType.UserDefined ? ConversionFactory.GetConversion(inputType, outputType) : ConversionFactory.GetPreDefinedConversion(inputType, outputType); if (conversion == null || conversion.ConversionType > conversionType) { return(null); } return(new Converter(conversion, il, inputType, outputType)); }
/// <summary> /// 将栈顶的对象从 <paramref name="inputType"/> 转换为 <paramref name="outputType"/>。 /// </summary> /// <param name="il">IL 指令生成器。</param> /// <param name="inputType">要转换的对象的类型。</param> /// <param name="outputType">要将输入对象转换到的类型。</param> /// <param name="isChecked">是否执行溢出检查。</param> /// <param name="conversionType">类型转换类型的限制。</param> internal static void EmitConversion(this ILGenerator il, Type inputType, Type outputType, bool isChecked, ConversionType conversionType) { Contract.Requires(il != null && inputType != null && outputType != null); Contract.Requires(conversionType == ConversionType.Implicit || conversionType == ConversionType.Explicit || conversionType == ConversionType.UserDefined); Conversion conversion = conversionType == ConversionType.UserDefined ? ConversionFactory.GetConversion(inputType, outputType) : ConversionFactory.GetPreDefinedConversion(inputType, outputType); if (conversion == null || conversion.ConversionType > conversionType) { throw CommonExceptions.InvalidCast(inputType, outputType); } if (conversion is FromNullableConversion) { il.EmitGetAddress(inputType); } conversion.Emit(il, inputType, outputType, isChecked); }
/// <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); DynamicMethod method = new DynamicMethod("Converter", buildGeneric ? outputType : typeof(object), new[] { buildGeneric?inputType: typeof(object) }, true); ILGenerator il = method.GetILGenerator(); bool 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.GetPreDefinedConversion(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>))); }