一,一些相關解釋 Service 在應用服務層也就是application層。應用服務用於將領域(業務)邏輯暴露給展現層。展現層通過傳入DTO(數據傳輸對象)參數來調用應用服務,而應用服務通過領域對象來執行相應的業務邏輯並且將DTO返回給展現層。 也就是這樣避免了應用服務層和展現層的,直接數據交互, ...
一,一些相關解釋
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("[email protected]", 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