溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

.NET?6開發(fā)TodoList應用怎么實現(xiàn)數(shù)據(jù)塑形

發(fā)布時間:2022-01-05 11:08:46 來源:億速云 閱讀:118 作者:iii 欄目:開發(fā)技術

這篇文章主要介紹“.NET 6開發(fā)TodoList應用怎么實現(xiàn)數(shù)據(jù)塑形”,在日常操作中,相信很多人在.NET 6開發(fā)TodoList應用怎么實現(xiàn)數(shù)據(jù)塑形問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”.NET 6開發(fā)TodoList應用怎么實現(xiàn)數(shù)據(jù)塑形”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

    需求

    在查詢的場景中,還有一類需求不是很常見,就是在前端請求中指定返回的字段,所以關于搜索的最后一個主題我們就來演示一下關于數(shù)據(jù)塑形(Data Shaping)。

    目標

    實現(xiàn)數(shù)據(jù)塑形搜索請求。

    原理與思路

    對于數(shù)據(jù)塑形來說,我們需要定義一些接口和泛型類實現(xiàn)來完成通用的功能,然后修改對應的查詢請求,實現(xiàn)具體的功能。

    實現(xiàn)

    定義通用接口和泛型類實現(xiàn)

    IDataShaper.cs

    using System.Dynamic;
    
    namespace TodoList.Application.Common.Interfaces;
    
    public interface IDataShaper<T>
    {
        IEnumerable<ExpandoObject> ShapeData(IEnumerable<T> entities, string fieldString);
        ExpandoObject ShapeData(T entity, string fieldString);
    }

    并實現(xiàn)通用的功能:

    DataShaper.cs

    using System.Dynamic;
    using System.Reflection;
    using TodoList.Application.Common.Interfaces;
    
    namespace TodoList.Application.Common;
    
    public class DataShaper<T> : IDataShaper<T> where T : class
    {
        public PropertyInfo[] Properties { get; set; }
    
        public DataShaper()
        {
            Properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        }
    
        public IEnumerable<ExpandoObject> ShapeData(IEnumerable<T> entities, string? fieldString)
        {
            var requiredProperties = GetRequiredProperties(fieldString);
    
            return GetData(entities, requiredProperties);
        }
    
        public ExpandoObject ShapeData(T entity, string? fieldString)
        {
            var requiredProperties = GetRequiredProperties(fieldString);
    
            return GetDataForEntity(entity, requiredProperties);
        }
    
        private IEnumerable<PropertyInfo> GetRequiredProperties(string? fieldString)
        {
            var requiredProperties = new List<PropertyInfo>();
    
            if (!string.IsNullOrEmpty(fieldString))
            {
                var fields = fieldString.Split(',', StringSplitOptions.RemoveEmptyEntries);
                foreach (var field in fields)
                {
                    var property = Properties.FirstOrDefault(pi => pi.Name.Equals(field.Trim(), StringComparison.InvariantCultureIgnoreCase));
                    if (property == null)
                    {
                        continue;
                    }
    
                    requiredProperties.Add(property);
                }
            }
            else
            {
                requiredProperties = Properties.ToList();
            }
    
            return requiredProperties;
        }
    
        private IEnumerable<ExpandoObject> GetData(IEnumerable<T> entities, IEnumerable<PropertyInfo> requiredProperties)
        {
            return entities.Select(entity => GetDataForEntity(entity, requiredProperties)).ToList();
        }
    
        private ExpandoObject GetDataForEntity(T entity, IEnumerable<PropertyInfo> requiredProperties)
        {
            var shapedObject = new ExpandoObject();
            foreach (var property in requiredProperties)
            {
                var objectPropertyValue = property.GetValue(entity);
                shapedObject.TryAdd(property.Name, objectPropertyValue);
            }
    
            return shapedObject;
        }
    }

    定義擴展方法

    為了使我們的Handle方法調(diào)用鏈能夠直接應用,我們在Application/Extensions中新增一個DataShaperExtensions:

    DataShaperExtensions.cs

    using System.Dynamic;
    using TodoList.Application.Common.Interfaces;
    
    namespace TodoList.Application.Common.Extensions;
    
    public static class DataShaperExtensions
    {
        public static IEnumerable<ExpandoObject> ShapeData<T>(this IEnumerable<T> entities, IDataShaper<T> shaper, string? fieldString)
        {
            return shaper.ShapeData(entities, fieldString);
        }
    }

    然后再對我們之前寫的MappingExtensions靜態(tài)類中添加一個方法:

    MappingExtensions.cs

    // 省略其他...
    public static PaginatedList<TDestination> PaginatedListFromEnumerable<TDestination>(this IEnumerable<TDestination> entities, int pageNumber, int pageSize)
    {
        return PaginatedList<TDestination>.Create(entities, pageNumber, pageSize);   
    }

    添加依賴注入

    在Application的DependencyInjection.cs中添加依賴注入:

    DependencyInjection.cs

    // 省略其他
    services.AddScoped(typeof(IDataShaper<>), typeof(DataShaper<>));

    修改查詢請求和Controller接口

    我們在上一篇文章實現(xiàn)排序的基礎上增加一個字段用于指明數(shù)據(jù)塑形字段并對應修改Handle方法:

    GetTodoItemsWithConditionQuery.cs

    using System.Dynamic;
    using AutoMapper;
    using AutoMapper.QueryableExtensions;
    using MediatR;
    using TodoList.Application.Common.Extensions;
    using TodoList.Application.Common.Interfaces;
    using TodoList.Application.Common.Mappings;
    using TodoList.Application.Common.Models;
    using TodoList.Application.TodoItems.Specs;
    using TodoList.Domain.Entities;
    using TodoList.Domain.Enums;
    
    namespace TodoList.Application.TodoItems.Queries.GetTodoItems;
    
    public class GetTodoItemsWithConditionQuery : IRequest<PaginatedList<ExpandoObject>>
    {
        public Guid ListId { get; set; }
        public bool? Done { get; set; }
        public string? Title { get; set; }
        // 前端指明需要返回的字段
        public string? Fields { get; set; }
        public PriorityLevel? PriorityLevel { get; set; }
        public string? SortOrder { get; set; } = "title_asc";
        public int PageNumber { get; set; } = 1;
        public int PageSize { get; set; } = 10;
    }
    
    public class GetTodoItemsWithConditionQueryHandler : IRequestHandler<GetTodoItemsWithConditionQuery, PaginatedList<ExpandoObject>>
    {
        private readonly IRepository<TodoItem> _repository;
        private readonly IMapper _mapper;
        private readonly IDataShaper<TodoItemDto> _shaper;
    
        public GetTodoItemsWithConditionQueryHandler(IRepository<TodoItem> repository, IMapper mapper, IDataShaper<TodoItemDto> shaper)
        {
            _repository = repository;
            _mapper = mapper;
            _shaper = shaper;
        }
    
        public Task<PaginatedList<ExpandoObject>> Handle(GetTodoItemsWithConditionQuery request, CancellationToken cancellationToken)
        {
            var spec = new TodoItemSpec(request);
            return Task.FromResult(
                _repository
                    .GetAsQueryable(spec)
                    .ProjectTo<TodoItemDto>(_mapper.ConfigurationProvider)
                    .AsEnumerable()
                    // 進行數(shù)據(jù)塑形和分頁返回
                    .ShapeData(_shaper, request.Fields)
                    .PaginatedListFromEnumerable(request.PageNumber, request.PageSize)
                );
        }
    }

    對應修改Controller:

    TodoItemController.cs

    [HttpGet]
    public async Task<ApiResponse<PaginatedList<ExpandoObject>>> GetTodoItemsWithCondition([FromQuery] GetTodoItemsWithConditionQuery query)
    {
        return ApiResponse<PaginatedList<ExpandoObject>>.Success(await _mediator.Send(query));
    }

    驗證

    啟動Api項目,執(zhí)行查詢TodoItem的請求:

    請求

    .NET?6開發(fā)TodoList應用怎么實現(xiàn)數(shù)據(jù)塑形

    響應

    .NET?6開發(fā)TodoList應用怎么實現(xiàn)數(shù)據(jù)塑形

    我們再把之前講到的過濾和搜索添加到請求里來:

    請求

    .NET?6開發(fā)TodoList應用怎么實現(xiàn)數(shù)據(jù)塑形

    響應

    .NET?6開發(fā)TodoList應用怎么實現(xiàn)數(shù)據(jù)塑形

    到此,關于“.NET 6開發(fā)TodoList應用怎么實現(xiàn)數(shù)據(jù)塑形”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

    向AI問一下細節(jié)

    免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

    AI