using Prism.Ioc;
using Prism.Modularity;
using Prism.Unity;
using Serilog;
using System;
using System.Resources;
using System.Windows;
using XP.Common.Configs;
using XP.Common.Localization;
using XP.Common.Localization.Interfaces;
using XP.Common.Logging;
using XP.Common.Logging.Implementations;
using XP.Common.Logging.Interfaces;
using XP.Hardware.Plc.Abstractions;
using XP.Hardware.Plc.Core;
using XP.Hardware.Plc.Services;
using XP.Hardware.PLC.Configs;
using XP.Hardware.PLC.Helpers;
using XP.Hardware.PLC.Services;
using XP.Hardware.PLC.Sentry.Views;
using XP.Hardware.PLC.Views;
namespace XP.Hardware.PLC.Sentry
{
///
/// PLC Sentry Monitor 应用程序入口 | PLC Sentry Monitor application entry point
///
public partial class App : PrismApplication
{
///
/// 应用程序日志实例(带模块上下文)| Application logger instance (with module context)
///
private ILogger _logger => Log.ForContext("SourceContext", "XP.Hardware.PLC.Sentry");
///
/// 创建主窗口 | Create main shell window
///
protected override Window CreateShell()
{
return Container.Resolve();
}
///
/// 注册类型到依赖注入容器 | Register types to DI container
///
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
// === 注册 XP.Common 基础服务 | Register XP.Common base services ===
containerRegistry.RegisterSingleton();
// === 注册 PLC 核心服务(复用 PLCModule 的注册模式)| Register PLC core services (reuse PLCModule registration pattern) ===
// IPlcClient 瞬态注册,每次 Resolve 创建独立实例,避免并发竞争
// IPlcClient registered as transient, each Resolve creates independent instance to avoid contention
containerRegistry.Register();
// PlcService 单例(依赖:IPlcClient, ILoggerService, XmlSignalParser)
// PlcService singleton (deps: IPlcClient, ILoggerService, XmlSignalParser)
containerRegistry.RegisterSingleton();
// IPlcService 接口映射到同一个 PlcService 单例 | IPlcService interface maps to same PlcService singleton
containerRegistry.Register(c => c.Resolve());
// 配置加载器(瞬态)| Configuration loader (transient)
containerRegistry.Register();
// XML 信号解析器(瞬态)| XML signal parser (transient)
containerRegistry.Register();
// PLC 写入队列单例(依赖:IPlcClient, ILoggerService)| PLC write queue singleton
containerRegistry.RegisterSingleton();
// 信号数据交互服务单例(依赖:PlcService, PlcWriteQueue, IPlcClient, ILoggerService)
// Signal data service singleton
containerRegistry.RegisterSingleton();
// === 注册 PLC 已有窗口 | Register existing PLC windows ===
containerRegistry.Register();
containerRegistry.Register();
// === 注册 Sentry 视图和 ViewModel | Register Sentry views and ViewModels ===
containerRegistry.Register();
containerRegistry.Register();
}
///
/// 配置模块目录 | Configure module catalog
///
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
// 注册通用模块(提供本地化、Dump 等基础服务)| Register common module (provides localization, dump, etc.)
moduleCatalog.AddModule();
base.ConfigureModuleCatalog(moduleCatalog);
}
///
/// 应用程序启动 | Application startup
///
protected override void OnStartup(StartupEventArgs e)
{
// 尽早注册非托管异常捕获 | Register unmanaged exception handler early
AppDomain.CurrentDomain.UnhandledException += (s, args) =>
{
var ex = args.ExceptionObject as Exception;
try
{
_logger.Fatal(ex, "检测到未处理异常(IsTerminating={IsTerminating})| Unhandled exception detected (IsTerminating={IsTerminating})", args.IsTerminating);
Log.CloseAndFlush();
// 向用户显示友好的错误提示 | Show friendly error message to user
MessageBox.Show(
$"应用发生严重错误,即将退出。请查看日志获取详细信息。\n\n{ex?.Message}\n\nA critical error occurred. The application will exit. Please check logs for details.",
"致命错误 | Fatal Error",
MessageBoxButton.OK,
MessageBoxImage.Error);
}
catch { /* 最后的防线 | Last resort */ }
};
// 加载并初始化 Serilog | Load and initialize Serilog
SerilogConfig serilogConfig = XP.Common.Helpers.ConfigLoader.LoadSerilogConfig();
SerilogInitializer.Initialize(serilogConfig);
_logger.Information("PLC Sentry Monitor 启动开始 | PLC Sentry Monitor startup started");
base.OnStartup(e);
}
///
/// 应用程序初始化完成 | Application initialization completed
///
protected override void OnInitialized()
{
base.OnInitialized();
// 注册模块级多语言资源到 Fallback Chain | Register module-level localization resources to Fallback Chain
try
{
var localizationService = Container.Resolve();
// 注册 PLC 模块的多语言资源(PlcAddrConfigEditorWindow 等窗口依赖)
// Register PLC module localization resources (required by PlcAddrConfigEditorWindow, etc.)
var plcResourceManager = new ResourceManager(
"XP.Hardware.PLC.Resources.Resources",
typeof(XP.Hardware.PLC.PLCModule).Assembly);
localizationService.RegisterResourceSource("XP.Hardware.PLC", plcResourceManager);
// 注册 Sentry 模块的多语言资源 | Register Sentry module localization resources
var resourceManager = new ResourceManager(
"XP.Hardware.PLC.Sentry.Resources.Resources",
typeof(App).Assembly);
localizationService.RegisterResourceSource("XP.Hardware.PLC.Sentry", resourceManager);
// 初始化 LocalizationHelper | Initialize LocalizationHelper
LocalizationHelper.Initialize(localizationService);
}
catch (Exception ex)
{
_logger.Warning(ex, "Sentry 多语言资源注册失败 | Sentry localization resource registration failed");
}
// 注册写入组件到 PlcService | Register write components to PlcService
var plcService = Container.Resolve();
var writeQueue = Container.Resolve();
var signalDataService = Container.Resolve() as SignalDataService;
plcService.RegisterWriteComponents(writeQueue, signalDataService?.DirectWriteChannel);
_logger.Information("PLC Sentry Monitor 初始化完成 | PLC Sentry Monitor initialization completed");
}
///
/// 应用程序退出 | Application exit
///
protected override void OnExit(ExitEventArgs e)
{
_logger.Information("PLC Sentry Monitor 退出 | PLC Sentry Monitor exiting");
Log.CloseAndFlush();
base.OnExit(e);
}
///
/// 捕获 UI 线程未处理异常 | Capture UI thread unhandled exceptions
///
private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
_logger.Fatal(e.Exception, "应用发生未处理异常 | Application encountered unhandled exception");
try
{
// 尝试刷新日志确保异常信息被持久化 | Flush logs to ensure exception info is persisted
Log.CloseAndFlush();
}
catch { /* 日志刷新失败不影响异常处理 | Log flush failure should not affect exception handling */ }
MessageBox.Show(
$"应用发生未处理异常,请查看日志获取详细信息。\n\n{e.Exception.Message}\n\nApplication encountered an unhandled exception. Please check logs for details.",
"错误 | Error",
MessageBoxButton.OK,
MessageBoxImage.Error);
// 标记异常已处理,防止应用崩溃 | Mark exception as handled to prevent app crash
e.Handled = true;
}
}
}