C#的λ表达式树学习
lambda 表达式树
可执行代码
Lambda表达式不仅可以用来创建委托实例,C#编译器也能够将他们转换成表达式树
(Lambda语句)
(Lambda表达式)
λ表达式树也是代码,我们把它当成另外一种动态语言学习就好了
λ表达式树最终的本质就是一个方法的编译状态
expression==(express.lambda)> lambda表达式树 ==(compile)》func委托
lambda, compile
表达式树 ,他的初始化是
Expression.Convert即等价于Convert静态类
将表达式树生成一个 委托(
Expression
提供了一种相对高级的抽象,允许你以更直观的方式创建和操作代码逻辑。它通常用于构建 LINQ 查询、动态生成委托等高级场景。
表达式树通常用于动态创建代码、代码分析、LINQ 查询等场景,而不是用于创建类。可以使用 Expression
类动态地创建 lambda 表达式,而这个 lambda 表达式可以用于创建新对象。但是,这个对象的类型通常是在编译时已知的,而不是在运行时动态创建的。
C#的λ表达式树(LambdaExpression)保姆级超详细简单入门教程 - 知乎 (zhihu.com)
通过Expression表达式树,为EF Core找回AddOrUpdate方法 - 知乎 (zhihu.com)
Masuit.Tools/Masuit.Tools.AspNetCore/AspNetCore/DbSetExtensions.cs at 382dc96506ac6ac87976332740053d313bd6f27b · ldqk/Masuit.Tools (github.com)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | /// <summary> /// 添加或更新 /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="TKey">按哪个字段更新</typeparam> /// <param name="dbSet"></param> /// <param name="keySelector">按哪个字段更新</param> /// <param name="entity"></param> public static void AddOrUpdate<T, TKey>( this DbSet<T> dbSet, Expression<Func<T, TKey>> keySelector, T entity) where T : class { if (keySelector == null ) { throw new ArgumentNullException(nameof(keySelector)); } if (entity == null ) { throw new ArgumentNullException(nameof(entity)); } var keyObject = keySelector.Compile()(entity); var parameter = Expression.Parameter( typeof (T), "p" ); var lambda = Expression.Lambda<Func<T, bool >>(Expression.Equal(ReplaceParameter(keySelector.Body, parameter), Expression.Constant(keyObject)), parameter); var item = dbSet.FirstOrDefault(lambda); if (item == null ) { dbSet.Add(entity); } else { // 获取主键字段 var dataType = typeof (T); var keyFields = dataType.GetProperties().Where(p => p.GetCustomAttribute<KeyAttribute>() != null ).ToList(); if (!keyFields.Any()) { string idName = dataType.Name + "Id" ; keyFields = dataType.GetProperties().Where(p => p.Name.Equals( "Id" , StringComparison.OrdinalIgnoreCase) || p.Name.Equals(idName, StringComparison.OrdinalIgnoreCase)).ToList(); } // 更新所有非主键属性 foreach ( var p in typeof (T).GetProperties().Where(p => p.GetSetMethod() != null && p.GetGetMethod() != null )) { // 忽略主键 if (keyFields.Any(x => x.Name == p.Name)) { continue ; } var existingValue = p.GetValue(entity); if (p.GetValue(item) != existingValue) { p.SetValue(item, existingValue); } } foreach ( var idField in keyFields.Where(p => p.GetSetMethod() != null && p.GetGetMethod() != null )) { var existingValue = idField.GetValue(item); if (idField.GetValue(entity) != existingValue) { idField.SetValue(entity, existingValue); } } } } private static Expression ReplaceParameter(Expression oldExpression, ParameterExpression newParameter) { return oldExpression.NodeType switch { ExpressionType.MemberAccess => Expression.MakeMemberAccess(newParameter, ((MemberExpression)oldExpression).Member), ExpressionType.New => Expression.New(((NewExpression)oldExpression).Constructor, ((NewExpression)oldExpression).Arguments.Select(a => ReplaceParameter(a, newParameter)).ToArray()), _ => throw new NotSupportedException( "不支持的表达式类型:" + oldExpression.NodeType) }; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?