一,一些相關解釋
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
