【ABP杂烩】Extensions后缀扩展方法

1.Extensions介绍

扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。 对于用 C#、F# 和 Visual Basic 编写的客户端代码,调用扩展方法与调用在类型中实际定义的方法没有明显区别。

详细见官方文档:扩展方法(C# 编程指南)

2.语法介绍

* 需要写在一个静态类中 
* 必须是一个静态方法 
* 通过第一个参数和this关键字指定扩展的目标类型 
* 不同类型的扩展方法不一定要写在同一个类中

3.事例介绍

 在ABP框架原中会发现在很多地方带有Extensions的类,其主要作用是在不改变原有接口或类的基础上扩展自定义的方法,从而方便使用,如QueryableExtensions类是对IQueryable进行扩展,里面添加了分页PageBy、条件判断WhereIf方法,代码如下:

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
using System;
using System.Linq;
using System.Linq.Expressions;
using Abp.Application.Services.Dto;
 
namespace Abp.Linq.Extensions
{
    /// <summary>
    /// Some useful extension methods for <see cref="IQueryable{T}"/>.
    /// </summary>
    public static class QueryableExtensions
    {
        /// <summary>
        /// Used for paging. Can be used as an alternative to Skip(...).Take(...) chaining.
        /// </summary>
        public static IQueryable<T> PageBy<T>(this IQueryable<T> query, int skipCount, int maxResultCount)
        {
            if (query == null)
            {
                throw new ArgumentNullException("query");
            }
 
            return query.Skip(skipCount).Take(maxResultCount);
        }
 
        /// <summary>
        /// Used for paging with an <see cref="IPagedResultRequest"/> object.
        /// </summary>
        /// <param name="query">Queryable to apply paging</param>
        /// <param name="pagedResultRequest">An object implements <see cref="IPagedResultRequest"/> interface</param>
        public static IQueryable<T> PageBy<T>(this IQueryable<T> query, IPagedResultRequest pagedResultRequest)
        {
            return query.PageBy(pagedResultRequest.SkipCount, pagedResultRequest.MaxResultCount);
        }
 
        /// <summary>
        /// Filters a <see cref="IQueryable{T}"/> by given predicate if given condition is true.
        /// </summary>
        /// <param name="query">Queryable to apply filtering</param>
        /// <param name="condition">A boolean value</param>
        /// <param name="predicate">Predicate to filter the query</param>
        /// <returns>Filtered or not filtered query based on <paramref name="condition"/></returns>
        public static IQueryable<T> WhereIf<T>(this IQueryable<T> query, bool condition, Expression<Func<T, bool>> predicate)
        {
            return condition
                ? query.Where(predicate)
                : query;
        }
 
        /// <summary>
        /// Filters a <see cref="IQueryable{T}"/> by given predicate if given condition is true.
        /// </summary>
        /// <param name="query">Queryable to apply filtering</param>
        /// <param name="condition">A boolean value</param>
        /// <param name="predicate">Predicate to filter the query</param>
        /// <returns>Filtered or not filtered query based on <paramref name="condition"/></returns>
        public static IQueryable<T> WhereIf<T>(this IQueryable<T> query, bool condition, Expression<Func<T, int, bool>> predicate)
        {
            return condition
                ? query.Where(predicate)
                : query;
        }
    }
}
 

 

如上所述,对IQueryable扩展后,可以像调用原生方法一样,使上层的调用感受不到区别和不用做过多的操作,方便对第三方的库进行扩展,从而增加自定义需求,有效提高项目的开发效率。调用代码如下:

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
public async Task<PagedResultDto<ProjectListDto>> GetProjects(GetProjectsInput input)
       {
           var query = _projectRepository.GetAll();
           query = query
               .WhereIf(!input.Name.IsNullOrWhiteSpace(), item => item.Name.Contains(input.Name))
               .WhereIf(!input.Address.IsNullOrWhiteSpace(), item => item.Address.Contains(input.Address))
               .WhereIf(!input.ResponbleDepart.IsNullOrWhiteSpace(), item => item.ResponbleDepart.Contains(input.ResponbleDepart))
               .WhereIf(!input.Type.IsNullOrWhiteSpace(), item => item.Type.Contains(input.Type))
               .WhereIf(input.ProjectDateStart.HasValue, item => item.StartTime >= input.ProjectDateStart)
               .WhereIf(input.ProjectDateEnd.HasValue, item => item.EndTime <= input.ProjectDateEnd)
               .WhereIf(input.ReportDateStart.HasValue, item => item.ReportTime >= input.ReportDateStart)
               .WhereIf(input.ReportDateEnd.HasValue, item => item.ReportTime <= input.ReportDateEnd);
 
 
           var projectCount = await query.CountAsync();
 
           var projects = await query.OrderBy(input.Sorting).PageBy(input).ToListAsync();
 
           var projectListDtos = ObjectMapper.Map<List<ProjectListDto>>(projects);
 
           return new PagedResultDto<ProjectListDto>(
               projectCount,
               projectListDtos
               );
       }

  

posted @   大龄Giser  阅读(757)  评论(0编辑  收藏  举报
编辑推荐:
· 分享一个我遇到过的“量子力学”级别的BUG。
· Linux系列:如何调试 malloc 的底层源码
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
阅读排行:
· Apifox不支持离线,Apipost可以!
· 历时 8 年,我冲上开源榜前 8 了!
· Trae 开发工具与使用技巧
· 通过 API 将Deepseek响应流式内容输出到前端
· 上周热点回顾(3.10-3.16)
点击右上角即可分享
微信分享提示