当类型转换表达式遇上自定义转换操作
浏览:1507次 出处信息
之前我提到说System.Json是一个十分不好用的类库,其中一点就是在于,我没法将一个JsonValue转化为范型类型――它只为Int32,String等几种特定类型定义了隐式转换,又无法得到以object类型所引用的值。不过这也难不到拥有“在运行时创建自定义表达式树并编译成动态代码”的.NET程序员。例如我们可以写这样一个辅助类进行JsonValue至任意类型的转化操作,.NET类库会负责为我们选择合适的转换方式:
class JsonConverter{ static JsonConverter() { var jsonValueExpr = Expression.Parameter(typeof(JsonValue), "jsonValue"); var convertExpr = Expression.Convert(jsonValueExpr, typeof(T)); var lambdaExpr = Expression.Lambda >(convertExpr, jsonValueExpr); s_convert = lambdaExpr.Compile(); } private static Func s_convert; public static T Convert(JsonValue jsonValue) { return s_convert(jsonValue); } }
泛型参数字典和动态代码生成都是性能的有效保证,而构造一颗我们需要的表达式树也十分容易。这个方法我以前也谈起过,我认为每个称职的.NET程序员都应该熟练掌握这种“通用操作”的实现方式。不过我最近在构造这种类型转换表达式的时候遇到了一些问题。例如,如果我们需要构造一个表达式,将一个JsonPrimitive(而不是先前的JsonValue)转化为int,这便会抛出一个异常,提示我们“没有合适的强制转化方式”。
我猜,可能是因为那些隐式转化操作定义在JsonValue上吧。那么这算不算一个Bug?我认为是,因为与它等价的代码是没有任何问题的,例如:
var value = (int)(new JsonPrimitive(10));
C#编译器会为我们找到JsonValue上定义的op_Implict方法并生成调用代码,而.NET类库却不会这么做,双方配合不够默契。不过其实这很容易绕开,只是我们要将这样的代码:
var convertExpr = Expression.Convert(instanceExpr, targetType);
修改为:
static Expression GetConvertExpression(Expression instanceExpr, Type targetType) { var mediateType = instanceExpr.Type; if (mediateType == typeof(object)) { // (TargetType)instance return Expression.Convert(instanceExpr, targetType); } while (mediateType != typeof(object)) { try { // (MediateType)instace var mediateExpr = Expression.Convert(instanceExpr, mediateType); // (TargetType)(MediateType)instance return Expression.Convert(mediateExpr, targetType); } catch { mediateType = mediateType.BaseType; } } throw new Exception(...); }
我们选择的策略很简单,提供一个“过渡类型”,先将instance转换为过渡类型,再转换成目标类型。如果发生转换错误,则会继续尝试其父类,直至object类型为止,则抛出异常表示转换失败。目前看来这个做法并没有什么问题。
建议继续学习:
- STRUTS2类型转换错误导致OGNL表达式注入漏洞分析 (阅读:9119)
- PHP数据类型隐性转换的陷阱 (阅读:2951)
- javascript运算/转换技巧 (阅读:2708)
- 编写安全代码:再论整数类型转换 (阅读:2619)
- JavaScript ( (__ = !$ + $)[+$] + ({} + $)[_/_] +({} + $)[_/_] ) (阅读:2589)
- 弱类型?C语言参数提升带来的一个陷阱 (阅读:2151)
- PHP类型转换相关的一个Bug (阅读:1967)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
扫一扫订阅我的微信号:IT技术博客大学习
<< 前一篇:情人节特献:有心之函数必然就有分手函数
后一篇:64位平台C/C++开发注意事项 >>
文章信息
- 作者:老赵 来源: 老赵点滴
- 标签: 类型转换
- 发布时间:2011-02-13 22:31:30
建议继续学习
近3天十大热文
- [66] Oracle MTS模式下 进程地址与会话信
- [66] Go Reflect 性能
- [65] 如何拿下简短的域名
- [59] android 开发入门
- [59] 图书馆的世界纪录
- [59] IOS安全–浅谈关于IOS加固的几种方法
- [58] 【社会化设计】自我(self)部分――欢迎区
- [53] 视觉调整-设计师 vs. 逻辑
- [47] 界面设计速成
- [46] 读书笔记-壹百度:百度十年千倍的29条法则