
多个表,不同的字段,一个业务他们处理逻辑相同
所以想用反射来减少点代码量,但是使用反射来获取值速度下降的厉害 ~ x5
async List<object> SelectValues<T>(IQueryable<T> queryable, string fieldName) where T : class { var type = typeof(T); var field = type.GetProperty(fieldName); if (field == null) throw new ArgumentNullException(nameof(fieldName)); var get = (T a) => (double?) field.GetValue(a); return queryable .Select(t => new { V = get(t) //非常慢 // V = t.field 速度正常 }).ToList(); } 有没有什么优化方案,或者不应该这么干?
1 leeg810312 2022-04-11 20:25:54 +08:00 via Android 在集合循环执行反射不合适,可以替换 fieldname 参数为 lambda 表达式参数 |
2 hackfly 2022-04-11 20:47:50 +08:00 定义一个泛型类,定义一个查询接口,每个表类派生,都实现各自查询接口,这样也多不了多少代码,就是多几个实力类 |
3 moen 2022-04-11 21:08:27 +08:00 GetProperty/GetValue 这一套下来慢是必然的。一种解决方案就是使用表达式树,生成一个获取 t.prop 的委托;第二种就是使用 Source Generator 把用到的 T 的所有属性的获取代码都生成出来,0 反射 |
4 你看看官方的集合扩展 Select 是怎么实现的,根本就不需要反射 |
5 userforg2021 2022-04-11 21:55:24 +08:00 你这个需求。。。不就是 Select 的功能吗。。。。 |
6 Rocketer 2022-04-11 23:09:07 +08:00 t.field 会被直接翻译成 sql 语句在数据库中执行,而反射只能把数据先取到内存中,转化成对象,再反射取值,当然慢。 更何况反射本身就慢。 你这个需求,可以使用 Dynamic LINQ 来替换 Select 里面的内容,从而使操作能最终变成 sql 语句。 官方例子就有: https://dynamic-linq.net/basic-simple-query |
7 beginor 2022-04-11 23:24:06 +08:00 这个只需要对 Linq 做一点儿扩展就够,就是构建简单的取属性的 lambda 表达式传进去就行了, 甚至都不需要第三方类库, 给你看一个动态添加排序的例子 https://github.com/beginor/appfx/blob/master/src/Core/LinqExtensions.cs#L64 |
8 ShareDuck 2022-04-12 09:04:04 +08:00 调用的时候,同样都要输入 fieldName ,也没有降低代码量吧。 |
9 coder001 2022-04-12 09:22:02 +08:00 在 IQueryable<T>用 AutoMapper 的 Projection 方法,可以生成查询表达式实现按需 Select |
10 yuhangch OP @leeg810312 @hackfly @moen @killergun @userforg2021 @Rocketer @beginor 感谢各位,先用 dynamic linq 顶一下,后面有时间了再看看表达式树的方法 (头天晚上焦头烂额,发个帖第二天早上解决了,v 站 up |