# 软件开发文档 - DMS.Application - 应用服务与DTOs
本文档详细阐述了 `DMS.Application` 层的设计。该层作为业务逻辑的协调者,负责处理用例、数据转换,并作为表现层与核心层的桥梁。
## 1. 目录结构
```
DMS.Application/
├── DTOs/
│ ├── DeviceDto.cs
│ ├── CreateDeviceDto.cs
│ ├── UpdateDeviceDto.cs
│ ├── VariableDto.cs
│ ├── VariableTableDto.cs
│ ├── MqttServerDto.cs
│ ├── VariableMqttAliasDto.cs
│ └── CreateDeviceWithDetailsDto.cs
├── Interfaces/
│ ├── IDeviceAppService.cs
│ ├── IMqttAppService.cs
│ ├── IVariableAppService.cs
│ ├── IMqttAliasAppService.cs
│ └── IMenuService.cs
├── Services/
│ ├── DeviceAppService.cs
│ ├── MqttAppService.cs
│ ├── VariableAppService.cs
│ ├── MqttAliasAppService.cs
│ └── MenuService.cs
├── Profiles/
│ └── MappingProfile.cs
└── DMS.Application.csproj
```
## 2. 应用服务设计
### 2.1. 设计思路与考量
* **职责**:应用服务(Application Services)是应用程序的用例(Use Case)实现者。它们负责编排领域模型和仓储来完成特定的业务操作,处理事务、授权、日志等应用级关注点。
* **依赖**:应用服务依赖于 `DMS.Core` 中定义的接口(如 `IRepositoryManager`),而不直接依赖 `DMS.Infrastructure` 的具体实现,遵循依赖倒置原则。
* **事务管理**:通过注入 `IRepositoryManager` 来管理事务,确保业务操作的原子性。
### 2.2. 设计优势
* **业务流程清晰**:每个应用服务方法对应一个具体的业务用例,代码结构清晰,易于理解业务流程。
* **解耦**:将业务逻辑与UI层和数据访问层解耦,提高了代码的可维护性和可测试性。
* **事务边界明确**:应用服务是定义事务边界的理想位置,确保业务操作的完整性。
* **可重用性**:应用服务可以被不同的客户端(如WPF UI、Web API等)复用。
### 2.3. 设计劣势/权衡
* **代码量增加**:相比于直接在UI层或仓储层编写业务逻辑,应用服务模式会增加一些代码量和抽象层级。
* **贫血应用服务**:如果应用服务仅仅是简单地调用仓储方法,而没有包含任何业务逻辑,则可能退化为“贫血应用服务”,失去了其应有的价值。
### 2.4. 示例:`IDeviceAppService.cs`
```csharp
// 文件: DMS.Application/Interfaces/IDeviceAppService.cs
using DMS.Application.DTOs;
using DMS.Core.Enums;
namespace DMS.Application.Interfaces;
///
/// 定义设备管理相关的应用服务操作。
///
public interface IDeviceAppService
{
///
/// 异步根据ID获取设备DTO。
///
Task GetDeviceByIdAsync(int id);
///
/// 异步获取所有设备DTO列表。
///
Task> GetAllDevicesAsync();
///
/// 异步创建一个新设备及其关联的变量表和菜单(事务性操作)。
///
/// 包含设备、变量表和菜单信息的DTO。
/// 新创建设备的ID。
Task CreateDeviceWithDetailsAsync(CreateDeviceWithDetailsDto dto);
///
/// 异步更新一个已存在的设备。
///
Task UpdateDeviceAsync(UpdateDeviceDto deviceDto);
///
/// 异步删除一个设备。
///
Task DeleteDeviceAsync(int id);
///
/// 异步切换设备的激活状态。
///
Task ToggleDeviceActiveStateAsync(int id);
///
/// 异步获取指定协议类型的设备列表。
///
Task> GetDevicesByProtocolAsync(ProtocolType protocol);
}
```
### 2.5. 示例:`DeviceAppService.cs`
```csharp
// 文件: DMS.Application/Services/DeviceAppService.cs
using AutoMapper;
using DMS.Core.Interfaces;
using DMS.Core.Models;
namespace DMS.Application.Services;
///
/// 实现设备管理的应用服务。
///
public class DeviceAppService : IDeviceAppService
{
private readonly IRepositoryManager _repoManager;
private readonly IMapper _mapper;
///
/// 构造函数,通过依赖注入获取仓储管理器和AutoMapper实例。
///
public DeviceAppService(IRepositoryManager repoManager, IMapper mapper)
{
_repoManager = repoManager;
_mapper = mapper;
}
///
/// 异步创建一个新设备及其关联的变量表和菜单(事务性操作)。
///
public async Task CreateDeviceWithDetailsAsync(CreateDeviceWithDetailsDto dto)
{
try
{
_repoManager.BeginTransaction();
var device = _mapper.Map(dto.Device);
device.IsActive = true; // 默认激活
await _repoManager.Devices.AddAsync(device);
// 假设 CreateDeviceWithDetailsDto 包含了变量表和菜单信息
if (dto.VariableTable != null)
{
var variableTable = _mapper.Map(dto.VariableTable);
variableTable.DeviceId = device.Id; // 关联新设备ID
await _repoManager.VariableTables.AddAsync(variableTable);
}
// 假设有菜单服务或仓储
// if (dto.Menu != null)
// {
// var menu = _mapper.Map