C#表达式树

这篇具有很好参考价值的文章主要介绍了C#表达式树。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C# 表达式树是 .NET 框架中的一项强大的功能,我们可以利用表达式树来动态生成 lambda 表达式和 LINQ 查询语句,这极大的方便了我们动态构建数据查询和过滤的逻辑。本文将从基本用法和高级用法两个方面来介绍 C# 表达式树。

基本用法

首先,我们需要了解 Expression 类型,这个类型是所有表达式树节点的基类,表达式树常用的基本节点类型还有 ConstantExpressionParameterExpressionBinaryExpressionLambdaExpression 等。下面是一个基本的例子:

using System;
using System.Linq.Expressions;

namespace ExpressionDemo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 创建参数和常量表达式
            ParameterExpression a = Expression.Parameter(typeof(int), "a");
            ConstantExpression b = Expression.Constant(2);

            // 创建加法表达式
            BinaryExpression c = Expression.Add(a, b);

            // 创建函数表达式
            Expression<Func<int, int>> func = Expression.Lambda<Func<int, int>>(c, a);

            // 执行以 (a + 2) 为表达式的函数
            Func<int, int> compiledFunc = func.Compile();
            Console.WriteLine(compiledFunc(1)); // 输出 3
        }
    }
}

首先,我们创建了一个 ParameterExpression 类型的变量 a 和一个 ConstantExpression 类型的常量 b。接着,我们定义了一个 “加法表达式” c,将 a 与 b 相加并返回。然后,我们使用 lambda 表达式将 c 作为函数体并传入了参数变量 a,返回类型为 int,即 Expression<Func<int,int>>。现在,我们可以使用 func.Compile() 将 lambda 表达式编译成可以直接调用的函数,并传入参数 1 调用该函数,实现了以 (a + 2) 为表达式的函数。最后,我们输出函数的结果 3

 

此外,我们还可以使用表达式树来构造 LINQ 查询语句,并执行查询和筛选。例如,我们可以使用表达式树来动态生成针对 List 中存储的对象的查询:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace ExpressionDemo
{
    class Person
    {
        public int Age { get; set; }
        public string Name { get; set; }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            // 构建一个 Person 列表
            List<Person> people = new List<Person>
            {
                new Person { Name = "Tom", Age = 23 },
                new Person { Name = "John", Age = 32 },
                new Person { Name = "Karen", Age = 28 }
            };

            // 动态构建查询表达式
            ParameterExpression p = Expression.Parameter(typeof(Person), "p");
            Expression ageExpr = Expression.Property(p, "Age");
            Expression valueExpr = Expression.Constant(30);
            Expression conditionExpr = Expression.GreaterThan(ageExpr, valueExpr);
            Expression<Func<Person, bool>> whereExpr = Expression.Lambda<Func<Person, bool>>(conditionExpr, p);
            IEnumerable<Person> resultSet = people.AsQueryable().Where(whereExpr);

            // 输出查询结果
            foreach (Person person in resultSet)
            {
                Console.WriteLine($"Name:{person.Name}, Age:{person.Age}");
            }
        }
    }
}

我们使用 Expression.Parameter 方法来创建一个参数 p,指定 Person 类型,并指定其参数名称 "p"。然后,我们以 p 为参数,使用 Expression.Property(p, "Age") 创建了一个表示参数对象的 Age 属性的 MemberExpression。接着,我们使用 Expression.Constant 方法创建了一个值 30 的常量表达式 valueExpr。我们使用 Expression.GreaterThan 方法将 ageExpr 和 valueExpr 联合起来构建了一个大于 30 的条件表达式 conditionExpr。最后,我们使用 Expression.Lambda 方法以 p 参数和 conditionExpr 表达式构建了一个 Func<Person, bool> 类型的 lambda 表达式 whereExpr。接着,我们使用了 people.AsQueryable().Where 方法将 whereExpr 表达式作为 lambda 参数传入,并执行查询。最后,我们遍历了 resultSet 输出了查询结果。

高级用法

在基本用法中,我们展示了如何使用表达式树来动态生成 lambda 表达式和 LINQ 查询语句。在实际开发中,还有一些更高级的用法可以充分地利用表达式树的能力,例如:

动态调用方法

在 C# 中,我们可以使用表达式树来动态地调用方法并获取方法的返回值。例如,我们可以动态地调用字符串的 Contains 方法:

using System;
using System.Linq.Expressions;

namespace ExpressionDemo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 创建字符串参数表达式
            ParameterExpression str = Expression.Parameter(typeof(string), "str");

            // 获取 Contains() 方法
            var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });

            // 创建 Contains() 方法调用表达式
            var call = Expression.Call(str, containsMethod, Expression.Constant("world"));

            // 编译表达式并执行
            var method = Expression.Lambda<Func<string, bool>>(call, str).Compile();
            Console.WriteLine(method("Hello, world!")); // 输出 True
        }
    }
}

我们使用 typeof(string).GetMethod("Contains", new[] { typeof(string) }) 获取 string 类型的 Contains 方法并传入 new[] { typeof(string) },指定该方法需要一个 string 类型的参数。接着,我们创建了一个调用 Contains 方法的表达式 call,即 Contains(str, "world")。最后,我们使用 Lambda 和 Compile 方法将表达式编译成可以直接执行的代码块并执行请求。

动态构造可调用对象

有时候,我们需要动态地构造一个可以调用的对象。例如,我们可以使用表达式树来创建一个可调用对象的实例,并将该实例作为参数传递给另一个函数。

using System;
using System.Linq.Expressions;

namespace ExpressionDemo
{
    interface ICalculator
    {
        double Add(double a, double b);
    }

    class AdditionCalculator : ICalculator
    {
        public double Add(double a, double b) => a + b;
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            // 创建 AdditionCalculator 的实例
            var constructor = Expression.New(typeof(AdditionCalculator).GetConstructor(new Type[0]));
            var additionCalculatorExpr = Expression.Convert(constructor, typeof(ICalculator));

            // 创建 Lambda 表达式,并调用 Add 方法
            var a = Expression.Parameter(typeof(double), "a");
            var b = Expression.Parameter(typeof(double), "b");
            var add = Expression.Call(additionCalculatorExpr, typeof(ICalculator).GetMethod("Add"), a, b);
            var expressionLambda = Expression.Lambda<Func<double, double, double>>(add, a, b);
            var additionFunc = expressionLambda.Compile();

            // 执行函数
            Console.WriteLine(additionFunc(1.5, 2.5)); // 输出 4.0
        }
    }
}

通过 Expression.New 方法创建 AdditionCalculator 对象的实例并转换为其接口类型 ICalculator。接着,我们调用了 ICalculator 的 Add 方法并将 additionCalculatorExpra 和 b 作为参数传递。然后,我们使用 Lambda 方法构建了一个 Func 委托类型,并调用 Compile 方法将其编译为可调用方法并执行请求。

总结

C# 表达式树是一个非常强大的工具,可以用于动态生成 lambda 表达式和 LINQ 查询,同时还可以用于动态调用方法、动态构造可调用对象和动态生成 C# 代码。在实际开发中,我们可以利用这些高级功能来优化代码,扩展应用的功能,提高应用的可维护性。文章来源地址https://www.toymoban.com/news/detail-432349.html

 

到了这里,关于C#表达式树的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • c# 动态表达式

    准备: 创建一个空项目,nuget查找并安装ExpressionEvaluator 示例: using ExpressionEvaluator; using System;  一、计算简单表达式        public string Test1()         {             return SimpleEval(\\\"0.1*(Math.Pow(10,2)+20)\\\");         }         /// summary         /// 简单数值计算         /// /summ

    2024年02月07日
    浏览(35)
  • 【c#表达式树】最完善的表达式树Expression.Dynamic的玩法

    在我第一次写博客的时候,写的第一篇文章,就是关于表达式树的,链接:https://www.cnblogs.com/1996-Chinese-Chen/p/14987967.html,其中,当时一直没有研究Expression.Dynamic的使用方法(因为网上找不到资料),就了解到是程序运行时动态去构建表达式树,举个例子,例如我们需要在我们的

    2023年04月11日
    浏览(36)
  • c#高级-正则表达式

    正则表达式是由普通字符和元字符(特殊符号)组成的文字形式 应用场景 1.用于验证输入的邮箱是否合法。 2.用于验证输入的电话号码是否合法。 3.用于验证输入的身份证号码是否合法。等等 正则表达式常用的限定符总结:    几种常用的正则简写表达式总结: 如下图所示

    2024年02月22日
    浏览(39)
  • C#正则表达式的使用

    如果不引用则写成 System.Text.RegularExpressions.Regex 使用方法如下: 符号 含义 d 0-9的数字 D d的补集,所有非数字的字符(同[^0-9]) w 单词字符,指大小写字母、0-9数字、下划线 W w的补集 s 空白字符,包括换行符n、回车符r、制表符t、垂直制表符v、换页符f S s的补集

    2024年02月08日
    浏览(63)
  • 以对象的方式访问html中的标签,比正则表达式更好用的方式获取html中的内容,linq方式直接获取所有的链接,更加先进的c#版本爬虫开源库

    这是我本人自己写的一个开源库,现已经发布到nuget,可以直接在vs的nuget包管理中搜索到,或者可以到nuget官网下载:https://www.nuget.org/packages/ZmjConvert/,也可以到我的个人网站上下载源码:https://www.zhaimaojun.cn/P/C%23%e6%a0%87%e7%ad%be%e7%b1%bb%e6%96%87%e6%9c%ac%e5%ba%8f%e5%88%97%e5%8c%96%e5%ba%9

    2024年03月15日
    浏览(52)
  • C# 正则表达式(Regex类)

    正则表达式是由普通字符(如英文字母)以及特殊字符(也称为元字符)组成的一种文字模式 这种文字模式可用于检查字符串的值是否满足一定的规则,例如: 验证输入的邮箱是否合法 输入的身份证号码是否合法 输入的用户名是否满足条件等 也可以进行字符串的替换和提

    2023年04月22日
    浏览(38)
  • C# 匿名方法和Lambda表达式

    1.匿名方法的演变 匿名方法是为了简化委托的实现,方便调用委托方法而出现的,同时,匿名方法也是学好lambda表达式的基础。在委托调用的方法中,如果方法只被调用一次,这个时候我们就没有必要创建具名方法,从而用匿名方法更为方便。 下面一段代码是声明并使用了一

    2024年02月15日
    浏览(44)
  • c#中lambda表达式缩写推演

     

    2024年02月12日
    浏览(35)
  • C# LINQ和Lambda表达式对照

    Linq语法: Lamda语法: sql语法: Linq语法: Lamda语法: sql语法: Linq语法: Lamda语法: sql语法: ​ Linq语法: Lamda语法: sql语法: ​ Linq语法: Lamda语法: sql语法: ​ Linq语法: Lamda语法: sql语法: Linq语法: Lamda语法: sql语法: ​ Linq语法: Lamda语法: EF Core中的写法:

    2024年02月16日
    浏览(36)
  • 三、C#—变量,表达式,运算符(3)

    变量名能不能用汉字? 全局变量 局部变量 错误1 错误2 错误3 2.2.1 值类型直接存储值 例如: 2.2.2 简单类型 2.2.3 整数类型 例如: 2.2.4 浮点类型 2.2.5 decimal 类型 注意: 定义decimal变量时的问题 2.2.6 bool类型 2.3.1 引用类型存储对值得引用 2.3.2 Object 类 不区分大小写得限制 2.3.3

    2024年02月09日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包