当前位置: 首页 > news >正文

对实体类Id自增

我们首先需要明白

lambda 表达式  (item=>item.Id)↓
Expression 树   →  检查是属性访问↓
Expression.Assign → 拼出 “item.Id = index”↓
Compile() → 生成机器码委托  Action<T,int>↓
放进 ConcurrentDictionary 缓存,终身复用

在原生的Linq中,我们可以写

List<Student> Students=CreateStudent();
Students.Select((item, index) => { item.Id = index; return item; });

我们可以自定义一个

Students.SelectWithIndex(item=>item.Id);
  /// <summary>/// 对序列按索引赋值,指定成员表达式 item => item.Id/// </summary>public static IEnumerable<T> SelectWithIndex<T>(this IEnumerable<T> source, Expression<Func<T, int>> memberSelector){if (source == null) throw new ArgumentNullException(nameof(source));if (memberSelector == null) throw new ArgumentNullException(nameof(memberSelector));// 编译一次 settervar setter = GetOrCreateSetter(memberSelector);return source.Select((item, idx) =>{setter(item, idx);return item;});}// 内部:把 Expression<item.Id> 编译成 Action<item,index>private static readonly ConcurrentDictionary<(Type, string), Delegate> _cache = new ConcurrentDictionary<(Type, string), Delegate>();
// ① 这是一个“编译并缓存”的工厂方法:输入 lambda (item=>item.Id) ,输出 Action<T,int> 委托
//    泛型 T 就是你要处理的模型类型,例如 MotionCalibrationModel
private static Action<T, int> GetOrCreateSetter<T>(Expression<Func<T, int>> selector)
{// ② 拿到 T 的运行时类型信息,后面要用它拼缓存键var type = typeof(T);// ③ 拼一个复合键:(类型, lambda 主体字符串)//    例如 (MotionCalibrationModel, "item.Id")  这样同一个类不同属性也能分开缓存var key = (type, selector.Body.ToString());// ④ ConcurrentDictionary 的 GetOrAdd 是线程安全的“获取或添加”//    如果缓存里已有这个键,直接返回已编译好的委托;否则执行 lambda 表达式编译逻辑return (Action<T, int>)_cache.GetOrAdd(key, _ =>{/* ⑤ 下面是“编译”过程,只做一次,以后复用 */// ⑥ 确保 lambda  body 是 item.Id  这种“取属性”形式if (!(selector.Body is MemberExpression mem) ||!(mem.Member is PropertyInfo prop) ||!prop.CanWrite ||                 // 必须有 set 访问器prop.PropertyType != typeof(int)) // 必须是 intthrow new ArgumentException("Lambda 必须返回一个可写的 int 属性,如 item => item.Id");// ⑦ 手工构造两个参数表达式//    paramItem  代表“将来传进来的对象”//    paramIndex 代表“将来传进来的索引值”var paramItem = Expression.Parameter(type, "item");var paramIndex = Expression.Parameter(typeof(int), "index");// ⑧ 构造赋值表达式:  item.Id = index//    左侧是“取属性”,右侧是“索引值”var assign = Expression.Assign(Expression.Property(paramItem, prop), paramIndex);// ⑨ 把赋值表达式包成 Lambda ://    (item, index) => item.Id = index//    Compile() 之后变成真正的委托 Action<T,int>return Expression.Lambda<Action<T, int>>(assign, paramItem, paramIndex).Compile();});
}
http://www.sczhlp.com/news/119290/

相关文章:

  • HarmonyOS之UIContext 与 UIAbility、WindowStage 的关系 - 指南
  • 向上一步——当做事纠结的人停止决策内耗,你就是掌控自己的神!
  • Windows平台安装cocos2d-x V3.17.2
  • 南通 网站建设旅游网站开发实验报告
  • 电子商务网站设计小结国内做的比较好的跨境电商网站
  • 免费做做网站开网店的流程视频
  • 网站信息安全保障制度建设情况google play谷歌商店
  • 如何提高网站访问速度的文章网站新闻列表页设计
  • 滨州制作网站网站内容设计是什么
  • 杭州专业制作网站中企动力科技股份有限公司怎么样
  • 济南网站建站公司制作网站参考
  • 北京网站建设华网装修高端网站建设
  • 网站登录密码怎么取消保存软件开发者怎么赚钱
  • 飞书机器人推送消息通知用自定义机器人
  • 如何加强网站建设和信息宣传网站一般用什么免费字体
  • 想接网站自己做成都做一个中小企业网站需要多少钱
  • 大英做网站免费网站建设排行表
  • 菜鸟教程网站是怎么做的如何进行目的地网站建设
  • 环艺毕业设计代做网站免费asp网站空间
  • 官方网站优化方法正规拉新推广平台有哪些
  • 浙江绿建设计院网站做网站怎么注册营业执照
  • 网站建设的具体步骤北京电力交易中心史连军
  • 哪家网站设计好app上架要多少钱
  • 虚拟主机网站建设步骤?英文网站建设 深圳
  • 南宁网站seo服务wordpress速度优化简书
  • 培训网站建设方案书佛山规划建设局网站
  • 做数码后期上数码网站江西赣州简介
  • 泰安建设网站自动跳转到wap网站
  • ENSP 常用命令
  • 珠海建站联系方式浙江耀华建设集团网站