YZWater3 已引入 Microsoft.Extensions.DependencyInjection 框架,采用渐进式迁移策略,从静态服务逐步过渡到依赖注入。
INotificationService - 通知服务(企业微信/钉钉/邮件)PlcService - PLC 通信AlarmService - 报警管理DatabaseService - 数据库AuthService - 认证授权ConfigService - 配置管理HubServer / HubClient - WebSocket 通信// 获取服务
var notificationService = ServiceLocator.GetService<INotificationService>();
// 发送通知
await notificationService.SendAlarmNotificationAsync(alarm);
public class MyViewModel : ObservableObject
{
private readonly INotificationService _notificationService;
public MyViewModel(INotificationService notificationService)
{
_notificationService = notificationService;
}
public async Task SomeMethod()
{
await _notificationService.SendAlarmNotificationAsync(alarm);
}
}
// 现有代码无需修改,继续使用静态类
NotificationService.Instance.SendAlarmNotificationAsync(alarm);
在 App.axaml.cs 的 OnStartup 中:
using Microsoft.Extensions.DependencyInjection;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// 配置 DI
var services = new ServiceCollection();
services.AddYZWaterCore();
var serviceProvider = services.BuildServiceProvider();
ServiceLocator.Configure(serviceProvider);
// 原有初始化代码...
}
以 PlcService 为例:
创建实例类实现接口
// 新建 PlcServiceImpl.cs
public class PlcServiceImpl : IPlcService
{
// 实现接口方法...
}
静态类作为门面(保持兼容)
// PlcService.cs 保持静态类
public static class PlcService
{
private static IPlcService? _impl;
public static void Initialize(IPlcService impl)
{
_impl = impl;
}
public static bool IsConnected => _impl?.IsConnected ?? false;
public static Task<bool> ConnectAsync()
=> _impl?.ConnectAsync() ?? Task.FromResult(false);
// 其他方法委托给 _impl...
}
在 DI 配置中注册
services.AddSingleton<IPlcService, PlcServiceImpl>();
初始化静态门面
var plcService = serviceProvider.GetRequiredService<IPlcService>();
PlcService.Initialize(plcService);
// 旧代码
PlcService.ConnectAsync();
// 新代码(ViewModel 中)
public class MyViewModel
{
private readonly IPlcService _plcService;
public MyViewModel(IPlcService plcService)
{
_plcService = plcService;
}
public async Task Connect()
{
await _plcService.ConnectAsync();
}
}
public interface IPlcService
{
bool IsConnected { get; }
Task<bool> ConnectAsync();
void Disconnect();
Task<byte[]?> ReadBytesAsync(string address, ushort length);
Task<float> ReadFloatAsync(string address);
Task<bool> ReadBoolAsync(string address);
Task<bool> WriteAsync(string address, byte[] value);
float ParseFloat(byte[] data, int offset);
bool ParseBit(byte[] data, int byteOffset, int bitIndex);
}
public interface IAlarmService
{
bool HasActiveAlarm { get; }
int ActiveAlarmCount { get; }
void Start();
void Stop();
Task AcknowledgeAlarmAsync(int alarmId, string operatorName = "Operator");
Task AcknowledgeAllAsync(string operatorName = "Operator");
Task<List<AlarmRecord>> GetUnacknowledgedAlarmsAsync();
Task<List<AlarmRecord>> GetAlarmHistoryAsync(DateTime start, DateTime end);
event Action<AlarmRecord>? AlarmRaised;
event Action<AlarmRecord>? AlarmAcknowledged;
event Action? AlarmStateChanged;
}
public interface INotificationService
{
bool IsEnabled { get; set; }
void AddChannel(INotificationChannel channel);
void RemoveChannel(string channelName);
Task SendNotificationAsync(string key, string title, string message, NotificationLevel level);
Task SendAlarmNotificationAsync(AlarmRecord alarm);
Task SendEscalationNotificationAsync(AlarmRecord alarm);
Task SendPlcConnectionNotificationAsync(bool isConnected);
}
使用 DI 后,可以方便地进行单元测试:
[Fact]
public async Task AlarmService_ShouldRaiseNotification_WhenAlarmTriggered()
{
// Arrange
var mockNotification = new Mock<INotificationService>();
var alarmService = new AlarmService(mockNotification.Object);
// Act
alarmService.TriggerAlarm("Test", "Test alarm", 2);
// Assert
mockNotification.Verify(x => x.SendAlarmNotificationAsync(It.IsAny<AlarmRecord>()), Times.Once);
}
高优先级(影响可测试性)
PlcService - 核心业务逻辑AlarmService - 报警判断AuthService - 权限检查中优先级(影响模块化)
DatabaseService - 数据访问ConfigService - 配置管理低优先级(相对独立)
HubServer / HubClient - 通信层AuditService - 审计日志