C#表达式树

科技资讯 投稿 6100 0 评论

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

 

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 输出了查询结果。

高级用法

动态调用方法

在 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# 代码。在实际开发中,我们可以利用这些高级功能来优化代码,扩展应用的功能,提高应用的可维护性。

 

编程笔记 » C#表达式树

赞同 (27) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽