测试Convert.ChangeType是否适用于两种类型

这是关于使用reflection转换值的问题的后续行动。 将某种类型的对象转换为另一种类型可以这样做:

object convertedValue = Convert.ChangeType(value, targetType); 

给定两个Type实例(比如FromType和ToType),有没有办法测试转换是否成功?

我可以写一个像这样的扩展方法:

 public static class TypeExtensions { public static bool CanChangeType(this Type fromType, Type toType) { // what to put here? } } 

编辑:这就是我现在所拥有的。 丑陋,但我还没有看到另一种方式……

 bool CanChangeType(Type sourceType, Type targetType) { try { var instanceOfSourceType = Activator.CreateInstance(sourceType); Convert.ChangeType(instanceOfSourceType, targetType); return true; // OK, it can be converted } catch (Exception ex) { return false; } 

我刚刚遇到同样的问题,我使用Reflector来查看ChangeType的源代码。 ChangeType在3种情况下抛出exception:

  1. conversionType为null
  2. value为null
  3. 值不实现IConvertible

检查完3个后,保证可以转换。 因此,您可以通过简单地自行检查这3个内容来节省大量性能并删除try {} / catch {}块:

 public static bool CanChangeType(object value, Type conversionType) { if (conversionType == null) { return false; } if (value == null) { return false; } IConvertible convertible = value as IConvertible; if (convertible == null) { return false; } return true; } 

检查reflection器中的Convert.ChangeType方法我在静态构造函数中找到了这个:

 ConvertTypes = new Type[] { typeof(Empty), typeof(object), typeof(DBNull), typeof(bool), typeof(char), typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal), typeof(DateTime), typeof(object), typeof(string) }; 

最后,此方法只是检查源是否正在实现IConvertible,或者目标是否是上面的ConvertTypes之一。 所以你的方法应该看起来像这样(非常粗糙):

 return (ConvertTypes.Contains(toType) || typeof(IConvertible).IsAssignableFrom(fromType)); 

我编写了一个包含Convert类的小框架,它可以比System.Convert类做更多。 如果您对使用它感兴趣,可以从CodePlex下载它。 它无法确定您是否可以在值之间进行转换,但这似乎是一个很好的添加function。

它确实包括基于以下内容转换值的function:

  • IConvertible
  • 类型转换器
  • ToXxx方法
  • 解析静态方法
  • 参数化构造函数
  • 以及其他一些小的

数据类型转换

根据我在这两个问题上已经回答的问题,我想出了这个问题,(需要c#7)

 public static object ChangeType(object value, Type conversion) { var type = conversion; if (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { if (value == null) { return null; } type = Nullable.GetUnderlyingType(type); } return Convert.ChangeType(value, type); } public static (bool IsSuccess, object Value) TryChangeType(object value, Type conversionType) { (bool IsSuccess, object Value) response = (false, null); var isNotConvertible = conversionType == null || value == null || !(value is IConvertible) || !(value.GetType() == conversionType); if (isNotConvertible) { return response; } try { response = (true, ChangeType(value, conversionType)); } catch (Exception) { response.Value = null; } return response; } } 

生产代码示例:

 public Item() { foreach (var pinfo in GetType().GetProperties()) { object value = 0; var response = ReflectionHelpers.TryChangeType(value, pinfo.PropertyType); if(response.IsSuccess) { pinfo.SetValue(this, response.Value); } } } 

这将启动所有可能的属性0。