/// <summary> /// 获取将对象从 <paramref name="inputType"/> 类型转换为 <paramref name="outputType"/> 类型的转换器。 /// </summary> /// <param name="inputType">要转换的对象的类型。</param> /// <param name="outputType">要将输入对象转换到的类型。</param> /// <param name="buildGeneric"><c>true</c> 表示需要生成泛型类型转换委托;<c>false</c> /// 表示需要生成非泛型的类型转换委托。</param> /// <returns>将对象从 <paramref name="inputType"/> 类型转换为 <paramref name="outputType"/> 类型的转换器。 /// 如果不存在则为 <c>null</c>。</returns> private static Converter GetConverterInternal(Type inputType, Type outputType, bool buildGeneric) { Contract.Requires(inputType != null && outputType != null); return(converterCache.GetOrAdd(new Tuple <Type, Type>(inputType, outputType), types => { var conversion = ConversionFactory.GetConversion(inputType, outputType); if (conversion == null) { return null; } var converter = new Converter(); var dlgConversion = conversion as DelegateConversion; if (dlgConversion != null) { converter.GenericConverter = dlgConversion.Converter; if (buildGeneric) { return converter; } } if (conversion.ConversionType == ConversionType.Identity || conversion.ConversionType == ConversionType.ImplicitReference || conversion.ConversionType == ConversionType.Box || conversion.ConversionType == ConversionType.Unbox) { converter.ObjectConverter = defaultObjectConverter; if (!buildGeneric) { return converter; } } if (conversion.ConversionType == ConversionType.ExplicitReference) { // 对于显式引用转换,只需要检查一下实际类型是否是 outputType 即可。 converter.ObjectConverter = obj => { if (obj != null && !outputType.IsInstanceOfType(obj)) { throw CommonExceptions.InvalidCast(obj.GetType(), outputType); } return obj; }; if (!buildGeneric) { return converter; } } var dlg = BuildConverter(conversion, inputType, outputType, false, buildGeneric); if (buildGeneric) { converter.GenericConverter = dlg; } else { converter.ObjectConverter = (Converter <object, object>)dlg; } return converter; })); }
/// <summary> /// 返回指定类型的对象,其值等效于指定对象。 /// </summary> /// <typeparam name="TInput">要转换的对象的类型。</typeparam> /// <typeparam name="TOutput">要将 <paramref name="value"/> 转换到的类型。</typeparam> /// <param name="value">要转换的对象。</param> /// <returns>一个对象,其类型为 <typeparamref name="TOutput"/>, /// 并且其值等效于 <paramref name="value"/>。</returns> /// <exception cref="InvalidCastException">不支持此转换。</exception> /// <overloads> /// <summary> /// 返回指定类型的对象,其值等效于指定对象。 /// </summary> /// </overloads> public static TOutput ChangeType <TInput, TOutput>(TInput value) { var converter = GetConverter <TInput, TOutput>(); if (converter == null) { throw CommonExceptions.InvalidCast(typeof(TInput), typeof(TOutput)); } return(converter(value)); }
/// <summary> /// 使用默认的类型转换方法将当前数组转换为另一种类型的数组。 /// </summary> /// <typeparam name="TInput">源数组元素的类型。</typeparam> /// <typeparam name="TOutput">目标数组元素的类型。</typeparam> /// <param name="array">要转换为目标类型的一维数组。</param> /// <returns>目标类型的数组,包含从源数组转换而来的元素。</returns> /// <exception cref="ArgumentNullException"><paramref name="array"/> 为 <c>null</c>。</exception> /// <exception cref="InvalidCastException"><typeparamref name="TInput"/> 类型不能转换到 /// <typeparamref name="TOutput"/> 类型。</exception> public static TOutput[] ConvertAll <TInput, TOutput>(this TInput[] array) { CommonExceptions.CheckArgumentNull(array, "array"); Contract.EndContractBlock(); Converter <TInput, TOutput> converter = Convert.GetConverter <TInput, TOutput>(); if (converter == null) { throw CommonExceptions.InvalidCast(typeof(TInput), typeof(TOutput)); } return(Array.ConvertAll(array, converter)); }
/// <summary> /// 返回指定类型的对象,其值等效于指定对象。 /// </summary> /// <typeparam name="TOutput">要转换到的类型。</typeparam> /// <param name="value">要将 <paramref name="value"/> 转换的对象。</param> /// <returns>一个对象,其类型为 <typeparamref name="TOutput"/>, /// 并且其值等效于 <paramref name="value"/>。</returns> /// <remarks>尽可能使用泛型方法 <see cref="ChangeType{TInput,TOutput}"/>,这样可以避免额外的类型转换。</remarks> /// <exception cref="InvalidCastException"><paramref name="value"/> 为 <c>null</c>, /// 而且 <typeparamref name="TOutput"/> 是值类型。</exception> /// <exception cref="InvalidCastException">不支持此转换。</exception> public static TOutput ChangeType <TOutput>(object value) { if (value == null) { if (typeof(TOutput).IsValueType) { throw CommonExceptions.CannotCastNullToValueType(); } return(default(TOutput)); } var converter = GetConverter(value.GetType(), typeof(TOutput)); if (converter == null) { throw CommonExceptions.InvalidCast(value.GetType(), typeof(TOutput)); } return((TOutput)converter(value)); }
/// <summary> /// 返回指定类型的对象,其值等效于指定对象。 /// </summary> /// <param name="value">要转换的对象。</param> /// <param name="outputType">要将 <paramref name="value"/> 转换到的类型。</param> /// <returns>一个对象,其类型为 <paramref name="outputType"/>, /// 并且其值等效于 <paramref name="value"/>。</returns> /// <remarks>尽可能使用泛型方法 <see cref="ChangeType{TInput,TOutput}"/>,这样可以避免额外的类型转换。</remarks> /// <exception cref="ArgumentNullException"><paramref name="outputType"/> 为 <c>null</c>。</exception> /// <exception cref="InvalidCastException"><paramref name="value"/> 为 <c>null</c>, /// 而且 <paramref name="outputType"/> 是值类型。</exception> /// <exception cref="InvalidCastException">不支持此转换。</exception> public static object ChangeType(object value, Type outputType) { CommonExceptions.CheckArgumentNull(outputType, nameof(outputType)); Contract.EndContractBlock(); if (value == null) { if (outputType.IsValueType) { throw CommonExceptions.CannotCastNullToValueType(); } return(null); } var converter = GetConverter(value.GetType(), outputType); if (converter == null) { throw CommonExceptions.InvalidCast(value.GetType(), outputType); } return(converter(value)); }