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)
            };
        }

   

待阅读:
 Expression Trees - C# | Microsoft Learn

posted @   Josen_Earth  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示