【ABP雜燴】Extensions字尾擴充套件方法
阿新 • • 發佈:2018-11-23
原文:
【ABP雜燴】Extensions字尾擴充套件方法
1.Extensions介紹
擴充套件方法使你能夠向現有型別“新增”方法,而無需建立新的派生型別、重新編譯或以其他方式修改原始型別。 擴充套件方法是一種特殊的靜態方法,但可以像擴充套件型別上的例項方法一樣進行呼叫。 對於用 C#、F# 和 Visual Basic 編寫的客戶端程式碼,呼叫擴充套件方法與呼叫在型別中實際定義的方法沒有明顯區別。
詳細見官方文件:擴充套件方法(C# 程式設計指南)
2.語法介紹
* 需要寫在一個靜態類中
* 必須是一個靜態方法
* 通過第一個引數和this關鍵字指定擴充套件的目標型別
* 不同型別的擴充套件方法不一定要寫在同一個類中
3.事例介紹
在ABP框架原中會發現在很多地方帶有Extensions的類,其主要作用是在不改變原有介面或類的基礎上擴充套件自定義的方法,從而方便使用,如QueryableExtensions類是對IQueryable進行擴充套件,裡面添加了分頁PageBy、條件判斷WhereIf方法,程式碼如下:
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擴充套件後,可以像呼叫原生方法一樣,使上層的呼叫感受不到區別和不用做過多的操作,方便對第三方的庫進行擴充套件,從而增加自定義需求,有效提高專案的開發效率。呼叫程式碼如下:
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 ); }