您的位置:首页 > 其它

自己动手写个ORM实现(4) 关于反射DataRow数据记录到实体性能的优化

2008-12-19 23:11 531 查看
总所周知,反射对于运行时确定对象类型十分方便,但是它最大的不足就是效率低下,比直接调用的效率慢了一百倍有余。

在3.5以前有codeDom或借助Emit直接编写IL来优化其效率,但是使用不便,借助3.5新增的Expression,让我们有了一种既简洁,在速度上又较反射有很大的提高。 示例如下

反射方式

1 public static T GetEntityByDataRowSlow<T>(this DataRow data) where T : new()

2 {

3 T t = new T();

4 PropertyInfo[] properties = typeof(T).GetProperties();

5

6 foreach (PropertyInfo p in properties)

7 {

8 object value = data[p.Name] == DBNull.Value ? null : data[p.Name];

9 p.SetValue(t, value, null);

10 }

11 return t;

12 }

如上,整段代码慢就慢在p.SetValue(t,value,null)这段上。 也有可能有人会说 typeof(T).GetProperties()获取所有属性应该缓存,但实际测试结果看下来影响并不大,效率相差无几。

接下来,主角登场了

1 static Func<T, object, object> GetSetDelegate<T>(MethodInfo m,Type type)

2 {

3

4 var param_obj = Expression.Parameter(typeof(T), "obj");

5 var param_val = Expression.Parameter(typeof(object), "val");

7 var body_val = Expression.Convert(param_val, type);

8 var body = Expression.Call(param_obj, m, body_val);

9 Action<T, object> set = Expression.Lambda<Action<T, object>>(body, param_obj, param_val).Compile();

10 return (instance, v) =>

11 {

12 set(instance, v);

13 return null;

14 };

15 }

1 static void FastSetValue<T>(this PropertyInfo property,T t, object value)

2 {

3 MethodInfo m = property.GetSetMethod();

4 GetSetDelegate<T>(m,property.PropertyType)(t, value);

5 }

关于Expression和lambda的介绍可参看园里大牛赵哥的文章 方法的直接调用,反射调用与……Lambda表达式调用

经过改良的调用方法

public static T FastGetEntityByDataRow<T>(this DataRow data) where T : new()

{

T t = new T();

PropertyInfo[] properties = GetProperties(typeof(T));

foreach (PropertyInfo p in properties)

{

object value = data[p.Name] == DBNull.Value ? null : data[p.Name];

p.FastSetValue<T>(t, value);

}

return t;

}

经过测试下来 如果直接是Entity.Property = "somevalue"设置属性的速度比值是1的话,反射的速度比值是100多,而经过改良的上述方法比值在2-3之间。

尽管这样,常见Web应用的主要瓶颈还是在结构的设计,数据库的读取,上面的方法对于整个程序框架的影响也只是积跬步,单用这个地方用了也几乎白用,不用白不用。谨记录一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: