众所周知,反射对于运行时确定对象类型十分方便,但是它最大的不足就是效率低下,比直接调用的效率慢了一百倍有余。
在3.5以前有codeDom或借助Emit直接编写IL来优化其效率,但是使用不便,借助3.5新增的Expr
反射方式
public static T GetEntityByDataRowSlow<T>(this DataRow da
{
T t = new T();
PropertyInfo[] properties = typeof(T).GetProperties();
foreach (PropertyInfo p in properties)
{
object value = da
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 = Expr
var param_val = Expr
var param_m = Expr
var body_val = Expr
var body = Expr
Act
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);
}
关于Expr
经过改良的调用方法
public static T FastGetEntityByDataRow<T>(this DataRow da
{
T t = new T();
PropertyInfo[] properties = GetProperties(typeof(T));
foreach (PropertyInfo p in properties)
{
object value = da
p.FastSetValue<T>(t, value);
}
return t;
}
经过测试下来 如果直接是Entity.Property = "somevalue"设置属性的速度比值是1的话,反射的速度比值是100多,而经过改良的上述方法比值在2-3之间