C#3.5新增的Expression来提升反射性能

众所周知,反射对于运行时确定对象类型十分方便,但是它最大的不足就是效率低下,比直接调用的效率慢了一百倍有余。

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

反射方式

public static T GetEntityByDataRowSlow<T>(this DataRow data) where T : new()
        {
            T t = new T();
            PropertyInfo[] properties = typeof(T).GetProperties();
            foreach (PropertyInfo p in properties)
            {
                object value = data[p.Name] == DBNull.Value ? null : data[p.Name];
                p.SetValue(t, value, null);
            }
            return t;
        }

 

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

static Func<T, MethodInfo, object, object> GetSetDelegate<T>(MethodInfo m, Type type)
        {
            var param_obj = Expression.Parameter(typeof(T), "obj");
            var param_val = Expression.Parameter(typeof(object), "val");
            var param_m = Expression.Parameter(typeof(MethodInfo), "m");
            var body_val = Expression.Convert(param_val, type);
            var body = Expression.Call(param_obj, m, body_val);
            Action<T, MethodInfo, object> set = Expression.Lambda<Action<T, MethodInfo, object>>(body, param_obj, param_m, param_val).Compile();
            return (instance, method, v) =>
            {
                set(instance, method, v);
                return null;

            };

}

static void FastSetValue<T>(this PropertyInfo property, T t, object value)
        {
            MethodInfo m = property.GetSetMethod();
            GetSetDelegate<T>(m, property.PropertyType)(t, m, value);
        }

关于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之间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值