一个比较通用的类型转换不是个容易的事情,开发中获取UI数据,或从数据库取回数据(没有使用ORM)的情况下,类型转换都显得特别繁琐,曾经写过非常丑陋的类型转换代码,下面这个略好一点,也能用在对象自动映射中。
类型转换代码
1 public class TypeHelper 2 { 3 /// <summary> 4 /// 只应该用来转换基本类型 5 /// </summary> 6 /// <param name="value"></param> 7 /// <param name="type"></param> 8 /// <param name="defaultVal"></param> 9 /// <returns></returns> 10 public static object ChangeType(object value, Type type, object defaultVal = null) 11 { 12 // 不传入类型,直接返回 13 if (type == null) return value; 14 15 // 不传入转换值,返回类型的默认值 16 if (value == null) return GetDefaultValue(type); 17 18 // 类型一致不需要转换 19 if (value.GetType() == type) return value; 20 21 // Nullable类型,把类型转换为实际类型 22 if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) 23 { 24 type = type.GetGenericArguments()[0]; 25 } 26 27 // 枚举类型处理 28 if (type.IsEnum) return ConvertToEnum(value, type); 29 30 // GUID类型处理 31 if (value is string && type == typeof(Guid)) 32 { 33 Guid guid; 34 Guid.TryParse(value as string, out guid); 35 return guid; 36 } 37 38 // bool类型增加与int类型的转换处理 39 if (type == typeof(bool)) 40 { 41 int i; 42 if (TryConvertToInt(value, out i)) 43 { 44 value = i != 0; 45 } 46 } 47 48 // 其他的转换 49 try 50 { 51 return System.Convert.ChangeType(value, type); 52 } 53 catch 54 { 55 return defaultVal ?? GetDefaultValue(type); 56 } 57 } 58 59 public static T ConvertTo<T>(object obj, T defalutValue = default(T)) 60 { 61 return (T)TypeHelper.ChangeType(obj, typeof(T), defalutValue); 62 } 63 64 private static bool TryConvertToInt(object value, out int result) 65 { 66 try 67 { 68 result = (int)System.Convert.ChangeType(value, typeof(int)); 69 return true; 70 } 71 catch 72 { 73 result = default(int); 74 return false; 75 } 76 } 77 78 private static object ConvertToEnum(object value, Type type) 79 { 80 if (value is string) 81 { 82 try 83 { 84 return Enum.Parse(type, value as string); 85 } 86 catch 87 { 88 return Activator.CreateInstance(type); 89 } 90 } 91 else 92 { 93 return Enum.ToObject(type, value); 94 } 95 } 96 97 private static object GetDefaultValue(Type type) 98 { 99 if (!type.IsValueType) return null; 100 101 if (!_defaultValues.ContainsKey(type)) 102 _defaultValues[type] = Activator.CreateInstance(type); 103 104 return _defaultValues[type]; 105 } 106 107 private static readonly Dictionary<Type, object> _defaultValues = new Dictionary<Type, object>(); 108 }
测试代码
1 [TestClass()] 2 public class TypeHelperTest 3 { 4 [TestMethod] 5 public void NormalTest() 6 { 7 Assert.AreEqual('1', TypeHelper.ChangeType("1", typeof(char))); 8 Assert.AreEqual(10, TypeHelper.ChangeType("10", typeof(int))); 9 Assert.AreEqual(10m, TypeHelper.ChangeType("10", typeof(decimal))); 10 } 11 12 [TestMethod] 13 public void NullArgumentTest() 14 { 15 Assert.AreEqual(null, TypeHelper.ChangeType(null, null)); 16 Assert.AreEqual(0, TypeHelper.ChangeType(null, typeof(int))); 17 Assert.AreEqual(0m, TypeHelper.ChangeType(null, typeof(decimal))); 18 Assert.AreEqual(null, TypeHelper.ChangeType(null, typeof(string))); 19 Assert.AreEqual("10", TypeHelper.ChangeType("10", null)); 20 Assert.AreEqual(10, TypeHelper.ChangeType(10, null)); 21 } 22 23 [TestMethod] 24 public void NullableTypeTest() 25 { 26 Assert.AreEqual(null, TypeHelper.ChangeType(null, typeof(int?))); 27 Assert.AreEqual(10, TypeHelper.ChangeType("10", typeof(int?))); 28 } 29 30 [TestMethod] 31 public void BoolTypeTest() 32 { 33 Assert.AreEqual(true, TypeHelper.ChangeType("true", typeof(bool))); 34 Assert.AreEqual(false, TypeHelper.ChangeType("false", typeof(bool))); 35 36 Assert.AreEqual(true, TypeHelper.ChangeType("TRUE", typeof(bool))); 37 Assert.AreEqual(false, TypeHelper.ChangeType("FALSE", typeof(bool))); 38 39 Assert.AreEqual(true, TypeHelper.ChangeType("1", typeof(bool))); 40 Assert.AreEqual(false, TypeHelper.ChangeType("0", typeof(bool))); 41 42 Assert.AreEqual(true, TypeHelper.ChangeType(1, typeof(bool))); 43 Assert.AreEqual(false, TypeHelper.ChangeType(0, typeof(bool))); 44 45 Assert.AreEqual(true, TypeHelper.ChangeType("11", typeof(bool))); 46 Assert.AreEqual(true, TypeHelper.ChangeType("-1", typeof(bool))); 47 } 48 49 [TestMethod] 50 public void EnumTypeTest() 51 { 52 Assert.AreEqual(TestEnum.A, TypeHelper.ChangeType(1, typeof(TestEnum))); 53 Assert.AreEqual(TestEnum.A, TypeHelper.ChangeType("1", typeof(TestEnum))); 54 Assert.AreEqual(TestEnum.A, TypeHelper.ChangeType("A", typeof(TestEnum))); 55 Assert.AreEqual((TestEnum)0, TypeHelper.ChangeType("a", typeof(TestEnum))); 56 } 57 58 [TestMethod] 59 public void GuidTypeTest() 60 { 61 Assert.AreEqual(Guid.Empty, TypeHelper.ChangeType(null, typeof(Guid))); 62 Assert.AreEqual(Guid.Empty, TypeHelper.ChangeType("dfdsfs", typeof(Guid))); 63 Assert.AreEqual(new Guid("{244F8EE2-DDD3-486A-B3E7-9EFDEEE4488C}"), TypeHelper.ChangeType("{244F8EE2-DDD3-486A-B3E7-9EFDEEE4488C}", typeof(Guid))); 64 } 65 } 66 67 public enum TestEnum 68 { 69 A = 1, B = 2 70 } 71 }