今天在工作上遇到这么个需求:需要获取对象上所有属性的值,但并事先并不知道对象的类型。 我的第一反应就是使用反射,但是这个操作会进行多次,大量的反射肯定会有性能影响。虽然对我这个项目无关紧要,但我还是选择了另外一种解决方案:构建表达式树,再生成委托,然后将委托缓存在字典里。代码如下:
首先构建表达式树(类似这种形式:'(a) => a.xx'),并生成委托:
代码如下 | 复制代码 |
private static Delegate BuildDynamicGetPropertyValueDelegate(PropertyInfo property) var lambdaExpression = Expression.Lambda(memberExpression, instanceExpression); |
接着,当需要获取属性的值时,先在字典里查看是否有已经生成好的委托,有的话取出委托执行获取属性值。没有则构建表达式树生成委托,并放入字典中:
代码如下 | 复制代码 |
private static Dictionary public static object GetPropertyValueUseExpression var getValueDelegate = BuildDynamicGetPropertyValueDelegate(property); |
就这么简单,完成之后,我想测试一下表达式树版本和反射版本的性能差距如何,于是我又简单实现反射版本作为测试对比:
代码如下 | 复制代码 |
public static object GetPropertyValueUseReflection { return propertyInfo.GetValue(obj); } |
接下来是两者的测试代码:
代码如下 | 复制代码 |
class Car ..... int repeatTimes = 10000; Stopwatch stopwatch = Stopwatch.StartNew(); stopwatch.Reset(); |
在我的预想之中是这样的:表达式树版本在调用次数很少的情况下会慢于反射版本,随着次数增多,表达式树版本的优势会越来越明显。
但是测试结果却出乎我的意料!!!
在调用次数为十万、百万、千万次的情况下,两者所用的时间差不多,而且反射版本居然还要快一些。这可让我郁闷不已。
郁闷之后,我就在想是不是因为字典的原因导致两者性能差不多,就添加了以下测试代码:
代码如下 | 复制代码 |
stopwatch.Reset(); stopwatch.Start(); var func = (Func for (int i = 0; i < repeatTimes; i++) { func(car); } stopwatch.Stop(); Console.WriteLine("Repeated {0}, Immediate call expression used time: {1} ticks", repeatTimes, stopwatch.ElapsedTicks); |
这部分测试代码,在构建表达式树生成委托之后,直接调用,去除了字典的影响。测试结果如下:
果不其然,去除字典之后速度快了10倍。
看来在我这种情况下使用字典缓存委托的效果并不是太好。不知道是否有更好的方法来缓存委托。
星球重启云游戏官方正版 安卓版v1.2.42
下载派对之星国际服 (flash party)安卓版v2.0.15.160832
下载Gym Fighting健身房格斗 安卓版v1.17.2
下载健身房格斗游戏无限金币 安卓版v1.18.2
下载幻兽爱合成小米版 最新版v2.5.6
幻兽爱合成小米版是一款非常好玩的宠物合成类游戏,游戏中有着海
修仙世家模拟器游戏 最新版v1.0.0
修仙世家模拟器是一款玩法新颖的模拟经营放置类挂机修仙游戏,游
国王或失败内购版 最新版v0.28.4
国王或失败内购版是一款非常好玩的模拟经营类手游,玩家在游戏中
飞影铠甲召唤器模拟器 最新版v1.0
飞影铠甲召唤器模拟器是一款可以模拟铠甲勇士变身音效和动作效果
幸福甜点咖啡店无限金币版 去广告版v1.2.2
幸福甜点咖啡店中文内购版是游戏的破解版本,在该版本中为玩家提