万能转换器blqw.Convert(1)
2018-06-05 本文已影响21人
冰麟轻武
一、
曾经很长一段时间,我在写代码的时候特别烦类型转换
当时int.TryParse(string,out int)
还没有out var
的语法,所以每次写起来特别麻烦(不算大括号也要3行)
所以自己动手写了一个 Convert3
现在正在着手把它搬到standard上所以又有了Convert4(未发布)
二、
在设计这个组件之初,我就决定了,它的调用必须是简单的,简单的和简单的
在经过一些思考之后,我发现类型转换一般只有3个场景
- 转换对象,转换失败时抛出异常
- 转换对象,转换失败时返回默认值
- 转换对象,并以out方式返回转换是否成功
所以最终的组件,只有3个主要的转换方法
而且为了调用更简单,3个方法以扩展方法形式提供,使用重载实现
所以整个API其实只有1个 obj.To...
// 3个泛型
Convert3.To<T>(this object obj); //转换失败,抛出异常
Convert3.To<T>(this object obj, T defaultValue); //转换失败,返回默认值
Convert3.To<T>(this object obj, out bool succeed); //输出转换是否成功
//3个是非泛型
Convert3.To(this object obj, Type outputType);
Convert3.To(this object obj, Type outputType, object defaultValue);
Convert3.To(this object obj, Type outputType, out bool succeed);
三、
调用
//假设有一个参数 object[] args
var id = args[0].To(0); //泛型类型自动推断
var name = args[1].To("");
var birthday = args[2].To(DateTime.MinValue);
if (id < 0)
throw new Exception("id必须大于0");
if (strubg.IsNullOrWhiteSpace(name))
throw new Exception("name不能为空");
if (birthday < new DateTime(1900,1,1) or birthday > DateTime.Today )
throw new Exception("请填写正确的日期");
四、
基于以上结果的思考,决定程序主体采用外观模式设计
这种情况下使用外观模式其实有三种选择:
- 根据参数类型获得转换器,转换器中实现将指定类型转换为任意类型的功能
interface IConvetor<in T> { object ConvertTo(T input); }
- 根据返回值类型获取转换器,转换器中实现将任意类型转为指定类型的功能
interface IConvetor<out T> { T ConvertTo(object input); }
- 根据参数类型和返回值类型同时匹配转换器
interface IConvetor<int TInput, out TOutput> { TOutput ConvertTo(TInput input); }
三总方式总的来说各有优缺点,在综合考虑了可读性,扩展性,性能及编码难度等因素后,最终选择了第2种方式来实现
未完待续
PS:如果文章可以帮到你,别忘了帮我点一下喜欢,让更多的人看到