ABP學習入門系列(四)(創建Service)


一,一些相關解釋

Service 在應用服務層也就是application層。應用服務用於將領域(業務)邏輯暴露給展現層。展現層通過傳入DTO(數據傳輸對象)參數來調用應用服務,而應用服務通過領域對象來執行相應的業務邏輯並且將DTO返回給展現層。

也就是這樣避免了應用服務層和展現層的,直接數據交互,而是通過dto實現了數據過濾,這樣就可以較好的避免非法數據的傳入傳出。另外大頭還要實現數據隱藏,方便擴展等好處。

創建應用服務時需要注意:

1.service 要實現IApplicationService接口。

2,ABP為IApplicationService提供默認實現ApplicationService

3,ABP中,一個應用服務方法默認是一個工作單元(Unit of Work)。ABP針對UOW模式自動進行數據庫的連接及事務管理,且會自動保存數據修改。

二,XXService和IXXService

1,如下TaskAppService 繼承了LearningMpaAbpAppServiceBase,並實現了ITaskAppService接口

using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.Events.Bus;
using Abp.Extensions;
using Abp.Linq.Extensions;
using Abp.Net.Mail.Smtp;
using Abp.Notifications;
using Abp.Runtime.Session;
using AutoMapper;
using LearningMpaAbp.Authorization;
using LearningMpaAbp.Authorization.Users;
using LearningMpaAbp.Tasks.Dtos;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;

namespace LearningMpaAbp.Tasks
{
    /// <summary>
    ///     Implements <see cref="ITaskAppService" /> to perform task related application functionality.
    ///     Inherits from <see cref="ApplicationService" />.
    ///     <see cref="ApplicationService" /> contains some basic functionality common for application services (such as
    ///     logging and localization).
    /// </summary>
    public class TaskAppService : LearningMpaAbpAppServiceBase, ITaskAppService
    {
        private readonly INotificationPublisher _notificationPublisher;
        private readonly ISmtpEmailSender _smtpEmailSender;
        //These members set in constructor using constructor injection.

        private readonly IRepository<Task> _taskRepository;
        private readonly IRepository<User, long> _userRepository;
        private readonly ITaskManager _taskManager;
        private readonly ITaskCache _taskCache;
        private readonly IEventBus _eventBus;

        /// <summary>
        ///     In constructor, we can get needed classes/interfaces.
        ///     They are sent here by dependency injection system automatically.
        /// </summary>
        public TaskAppService(
            IRepository<Task> taskRepository,
            IRepository<User, long> userRepository,
            ISmtpEmailSender smtpEmailSender,
            INotificationPublisher notificationPublisher,
            ITaskCache taskCache,
            ITaskManager taskManager,
            IEventBus eventBus)
        {
            _taskRepository = taskRepository;
            _userRepository = userRepository;
            _smtpEmailSender = smtpEmailSender;
            _notificationPublisher = notificationPublisher;
            _taskCache = taskCache;
            _taskManager = taskManager;
            _eventBus = eventBus;
        }

        public TaskCacheItem GetTaskFromCacheById(int taskId)
        {
            return _taskCache[taskId];
        }

        public IList<TaskDto> GetAllTasks()
        {
            var tasks = _taskRepository.GetAll().OrderByDescending(t => t.CreationTime).ToList();
            return Mapper.Map<IList<TaskDto>>(tasks);
        }

        public GetTasksOutput GetTasks(GetTasksInput input)
        {
            var query = _taskRepository.GetAllIncluding(t => t.AssignedPerson)
                .WhereIf(input.State.HasValue, t => t.State == input.State.Value)
                .WhereIf(!input.Filter.IsNullOrEmpty(), t => t.Title.Contains(input.Filter))
                .WhereIf(input.AssignedPersonId.HasValue, t => t.AssignedPersonId == input.AssignedPersonId.Value);

            //排序
            if (!string.IsNullOrEmpty(input.Sorting))
                query = query.OrderBy(input.Sorting);
            else
                query = query.OrderByDescending(t => t.CreationTime);

            var taskList = query.ToList();

            //Used AutoMapper to automatically convert List<Task> to List<TaskDto>.
            return new GetTasksOutput
            {
                Tasks = Mapper.Map<List<TaskDto>>(taskList)
            };
        }


        public PagedResultDto<TaskDto> GetPagedTasks(GetTasksInput input)
        {
            //初步過濾
            var query = _taskRepository.GetAllIncluding(t => t.AssignedPerson)
                .WhereIf(input.State.HasValue, t => t.State == input.State.Value)
                .WhereIf(!input.Filter.IsNullOrEmpty(), t => t.Title.Contains(input.Filter))
                .WhereIf(input.AssignedPersonId.HasValue, t => t.AssignedPersonId == input.AssignedPersonId.Value);

            //排序
            query = !string.IsNullOrEmpty(input.Sorting) ? query.OrderBy(input.Sorting) : query.OrderByDescending(t => t.CreationTime);

            //獲取總數
            var tasksCount = query.Count();
            //默認的分頁方式
            //var taskList = query.Skip(input.SkipCount).Take(input.MaxResultCount).ToList();

            //ABP提供了擴展方法PageBy分頁方式
            var taskList = query.PageBy(input).ToList();

            return new PagedResultDto<TaskDto>(tasksCount, taskList.MapTo<List<TaskDto>>());
        }

        public async Task<TaskDto> GetTaskByIdAsync(int taskId)
        {
            //Called specific GetAllWithPeople method of task repository.
            var task = await _taskRepository.GetAsync(taskId);

            //Used AutoMapper to automatically convert List<Task> to List<TaskDto>.
            return task.MapTo<TaskDto>();
        }

        public TaskDto GetTaskById(int taskId)
        {
            var task = _taskRepository.Get(taskId);

            return task.MapTo<TaskDto>();
        }

        public void UpdateTask(UpdateTaskInput input)
        {
            //We can use Logger, it's defined in ApplicationService base class.
            Logger.Info("Updating a task for input: " + input);

            //獲取是否有權限
            bool canAssignTaskToOther = PermissionChecker.IsGranted(PermissionNames.Pages_Tasks_AssignPerson);
            //如果任務已經分配且未分配給自己,且不具有分配任務權限,則拋出異常
            if (input.AssignedPersonId.HasValue && input.AssignedPersonId.Value != AbpSession.GetUserId() &&
                !canAssignTaskToOther)
            {
                throw new AbpAuthorizationException("沒有分配任務給他人的權限!");
            }

            var updateTask = Mapper.Map<Task>(input);
            var user = _userRepository.Get(input.AssignedPersonId.Value);
            //先執行分配任務
            _taskManager.AssignTaskToPerson(updateTask, user);

            //再更新其他字段
            _taskRepository.Update(updateTask);

        }

        public void AssignTaskToPerson(AssignTaskToPersonInput input)
        {
            var task = _taskRepository.Get(input.TaskId);
            var user = _userRepository.Get(input.UserId);
            _taskManager.AssignTaskToPerson(task, user);
            //這里有一個問題就是,當開發人員不知道有這個TaskManager時,依然可以通過直接修改Task的AssignedPersonId屬性就行任務分配。

            //分配任務成功后,觸發領域事件,發送郵件通知
            //_eventBus.Trigger(new TaskAssignedEventData(task, user));//由領域服務觸發領域事件

        }

        public int CreateTask(CreateTaskInput input)
        {
            //We can use Logger, it's defined in ApplicationService class.
            Logger.Info("Creating a task for input: " + input);

            //判斷用戶是否有權限
            if (input.AssignedPersonId.HasValue && input.AssignedPersonId.Value != AbpSession.GetUserId())
                PermissionChecker.Authorize(PermissionNames.Pages_Tasks_AssignPerson);

            var task = Mapper.Map<Task>(input);

            int result = _taskRepository.InsertAndGetId(task);

            //只有創建成功才發送郵件和通知
            if (result > 0)
            {
                if (input.AssignedPersonId.HasValue)
                {
                    var user = _userRepository.Load(input.AssignedPersonId.Value);
                    //task.AssignedPerson = user;
                    //var message = "You hava been assigned one task into your todo list.";

                    //使用領域事件觸發發送通知操作
                    _eventBus.Trigger(new TaskAssignedEventData(task, user));

                    //TODO:需要重新配置QQ郵箱密碼
                    //_smtpEmailSender.Send("ysjshengjie@qq.com", task.AssignedPerson.EmailAddress, "New Todo item", message);

                    //_notificationPublisher.Publish("NewTask", new MessageNotificationData(message), null,
                    //    NotificationSeverity.Info, new[] { task.AssignedPerson.ToUserIdentifier() });
                }
            }

            return result;
        }

       
        public void Delete(int id)
        {
            var task = _taskRepository.Get(id);
            if (task != null)
                _taskRepository.Delete(task);
        }
    }
}

2,ITaskAppService 繼承IApplicationService

using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;
using System.Threading.Tasks;
using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.Linq.Extensions;
using LearningMpaAbp.Tasks.Dtos;

namespace LearningMpaAbp.Tasks
{
    public interface ITaskAppService : IApplicationService
    {
        GetTasksOutput GetTasks(GetTasksInput input);

        PagedResultDto<TaskDto> GetPagedTasks(GetTasksInput input);

        void UpdateTask(UpdateTaskInput input);

        int CreateTask(CreateTaskInput input);

        Task<TaskDto> GetTaskByIdAsync(int taskId);

        TaskDto GetTaskById(int taskId);

        void Delete(int taskId);

        TaskCacheItem GetTaskFromCacheById(int taskId);

        IList<TaskDto> GetAllTasks();
    }
}

 

三,Dto 數據傳輸對象(Data Transfer Objects)用於應用層和展現層的數據傳輸

ABP 建議命名 input/ouput 對象類似於 MethodNameInput/MethodNameOutput,對於每個應用服務方法都需要將 Input Output 進行分開定義。甚至你的方法只接
收或者返回一個值,也最好創建相應的 DTO 類型。 這樣會使代碼有更好的擴展性

using System.Collections.Generic;

namespace LearningMpaAbp.Tasks.Dtos
{
    public class GetTasksOutput
    {
        public List<TaskDto> Tasks { get; set; }
    }
}

 有一個問題怎么將task實體類轉換為dto,這時就需要進行映射了AutoMapper 根據 Task實體創建了 taskDto,並根據命名約定來給
PersonDto 的屬性賦值 。

 

以上。。

參考:http://www.jianshu.com/p/da69ca7b27c6

代碼:https://github.com/tianxiangd/LearnAbp

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM