C#之Expression表达式树实例

C#之Expression表达式树实例

简介

Expression表达式树是C#中一种强大的语言特性,可以通过表达式树实现动态构建Lambda表达式,让开发者可以在运行时动态的创建查询、过滤、排序等功能,大大提高了程序的灵活性。本文将详细讲解如何使用Expression表达式树实现常见的功能。

示例一:动态查询

如下是一个简单的Person类:

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

现在我们需要根据Person对象的Name和Age属性进行查询,如果使用Linq语句,那么需要手动指定Name和Age的属性名:

List<Person> persons = new List<Person>
{
    new Person {Name = "张三", Age = 20},
    new Person {Name = "李四", Age = 30},
    new Person {Name = "王五", Age = 40},
};

// 查询Name为李四的Person
var person = persons.FirstOrDefault(p => p.Name == "李四");

// 查询Age大于等于30的Person列表
var personList = persons.Where(p => p.Age >= 30).ToList();

这种做法需要手动指定属性名,代码可读性和可维护性都不高,使用Expression表达式树可以很好的解决这个问题。我们定义一个动态查询的方法,可以根据传入的属性名称和属性值进行查询:

public static class PersonExtensions
{
    public static IQueryable<Person> WhereByNameAndAge(this IQueryable<Person> query, string name, int age)
    {
        var parameter = Expression.Parameter(typeof(Person), "p");
        var propertyExpr1 = Expression.Property(parameter, nameof(Person.Name));
        var propertyExpr2 = Expression.Property(parameter, nameof(Person.Age));
        var constantExpr1 = Expression.Constant(name, typeof(string));
        var constantExpr2 = Expression.Constant(age, typeof(int));
        var conditionExpr1 = Expression.Equal(propertyExpr1, constantExpr1);
        var conditionExpr2 = Expression.GreaterThanOrEqual(propertyExpr2, constantExpr2);
        var andExpr = Expression.AndAlso(conditionExpr1, conditionExpr2);
        var lambdaExpr = Expression.Lambda<Func<Person, bool>>(andExpr, parameter);
        return query.Where(lambdaExpr);
    }
}

这个方法接受一个IQueryable类型的查询对象,以及两个参数name和age。通过使用Expression方法构造Expression表达式树,然后返回一个查询结果。使用此方法进行查询:

var person = persons.WhereByNameAndAge("李四", 30).FirstOrDefault();
var personList = persons.WhereByNameAndAge("", 30).ToList();

示例二:动态排序

如下是一个简单的Product类:

public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

现在需要根据Product的Price属性进行排序,但是排序的方向(升序或者降序)是不确定的,我们需要动态构建Lambda表达式。如果使用Linq语句进行排序,需要手动判断排序方向:

List<Product> products = new List<Product>
{
    new Product {Name = "苹果", Price = 10},
    new Product {Name = "香蕉", Price = 5},
    new Product {Name = "橘子", Price = 20},
};

// 升序
var sortedProductsAsc = products.OrderBy(p => p.Price).ToList();

// 降序
var sortedProductsDesc = products.OrderByDescending(p => p.Price).ToList();

使用Expression表达式树可以强制指定排序方向,实现更加灵活的排序方法:

public static class ProductExtensions
{
    public static IQueryable<Product> OrderByPrice(this IQueryable<Product> query, bool isAscending)
    {
        var parameterExpr = Expression.Parameter(typeof(Product), "p");
        var propertyExpr = Expression.Property(parameterExpr, nameof(Product.Price));
        var lambdaExpr = Expression.Lambda(propertyExpr, parameterExpr);
        var methodName = isAscending ? "OrderBy" : "OrderByDescending";
        var methodExpr = Expression.Call(
            typeof(Queryable),
            methodName,
            new Type[] {query.ElementType, typeof(decimal)},
            query.Expression,
            lambdaExpr
        );
        return query.Provider.CreateQuery<Product>(methodExpr);
    }
}

该方法接收IQueryable类型的查询对象以及一个布尔类型的参数isAscending,该参数指定排序方向。通过Expression构造表达式树,然后使用反射调用OrderBy方法进行排序,最后返回排序结果。

var sortedProductsAsc = products.OrderByPrice(true).ToList();
var sortedProductsDesc = products.OrderByPrice(false).ToList();

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#之Expression表达式树实例 - Python技术站

(0)
上一篇 2023年6月1日
下一篇 2023年6月1日

相关文章

  • .Net的GC垃圾回收原理及实现

    .NET的GC垃圾回收原理及实现 在.NET中,垃圾回收(GC)是一种自动内存管理机制,它负责在运行时自动释放不再使用的内存。在本攻略中,我们将详细讲解.NET的GC垃圾回收原理及实现,并提供两个示例说明。 垃圾回收原理 .NET的GC垃圾回收原理基于以下两个核心概念: 1. 引用计数 引用计数是一种内存管理技术,它通过计算对象的引用数来确定对象是否可以被释…

    C# 2023年5月17日
    00
  • C#6 null 条件运算符

    C#6的null条件运算符(?.)是一种用于简化访问对象成员的语法糖。它主要用于避免在链式调用中出现空引用异常(NullReferenceException)。下面是使用该运算符的两个示例: 示例一:在引用可空类型时使用null条件运算符 假设我们有这样一个类: public class Person { public string Name { get; …

    C# 2023年5月15日
    00
  • C#中partial关键字的作用

    接下来我会详细讲解一下“C#中partial关键字的作用”。 什么是 partial 关键字 partial 是 C# 中的一个特殊关键字,用于修饰一个类、结构体、接口或方法,表示该类、结构体、接口或方法可分成多个部分进行定义。 partial 关键字的作用 使用 partial 关键字可以将一个类、结构体或接口的定义分拆到多个文件中进行定义。 这种方式的主…

    C# 2023年6月7日
    00
  • .NET Core自定义配置文件

    在本攻略中,我们将详细讲解.NET Core自定义配置文件的实现方法,并提供两个示例说明。 创建配置文件:首先,我们需要创建一个配置文件。我们可以使用JSON、XML或INI等格式来创建配置文件。例如,我们可以创建一个名为appsettings.json的JSON格式的配置文件,内容如下: { "MyConfig": { "Na…

    C# 2023年5月16日
    00
  • .NET中实现对象数据映射示例详解

    以下是“.NET中实现对象数据映射示例详解”的完整攻略: 什么是对象数据映射 对象数据映射(Object-Relational Mapping,ORM)是一种将对象模型和关系数据库之间的数据转换的技术。ORM可以将对象模型中的数据映射到关系数据库中,也将关系数据库中的数据映射到对象模中。 .NET中实现对象数据映射 在.NET中,我们可以使用多种ORM框架实…

    C# 2023年5月12日
    00
  • C# 特殊的string类型详解

    C# 特殊的string类型详解 什么是C#中的string类型 在C#中,字符串被定义为一系列字符的序列。C#中的string类型是个类,因此声明一个字符串时需要使用string关键字。例如: string myString = "Hello, world!"; 在上面的代码中,我们声明了一个字符串变量myString,并且将字符串常量…

    C# 2023年5月31日
    00
  • C#实现根据字节数截取字符串并加上省略号的方法

    当我们需要在页面上展示一篇文章标题或者一段文字时,经常会遇到字数过多的情况。这时候我们可以使用 C# 实现的截取字符串的方法来实现并在尾部加上省略号,提高用户体验。 下面是实现的完整攻略: 1.确定要截取的字节数 首先需要确定截取的字节数。这里需要注意的是一个汉字在 utf-8 编码下占用三个字节,而在 gb2312/GBK 编码下占用两个字节。因此我们需要…

    C# 2023年6月8日
    00
  • C# 各种导出的方法总结

    C#是一门比较流行的编程语言,它常被用于Windows平台的软件开发。C#代码开发完毕后,如何将代码打包成程序或者发布给其他开发者使用呢?这就要用到C#中的导出方法。 本篇文章将为大家总结C#中各种导出方法,包括命令行工具和IDE插件等,以及每种方法的优缺点,希望能够帮助大家更好地理解和使用C#。 1. 命令行工具 1.1. .NET Core SDK .N…

    C# 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部