WPF中App.xaml.cs依赖注入时的异常处理方案咨询
解决方案
一、在应用启动入口捕获异常并弹出提示
WPF启动阶段的DI初始化异常会直接终止进程,你可以在App.xaml.cs的OnStartup方法(或.NET 6+的Program.cs主入口)中包裹服务提供者的构建逻辑,统一捕获异常后弹出提示框:
示例代码(App.xaml.cs)
protected override void OnStartup(StartupEventArgs e) { try { var services = new ServiceCollection(); // 注册其他依赖服务 services.AddSingleton<IConfiguracionServicio, ConfiguracionServicioImpl>(); // 注册CanalGrpc services.AddSingleton<CanalGrpc>(miServiceProvider => { string miStrDireccionServidor = GetDireccionServidor(miServiceProvider.GetRequiredService<IConfiguracionServicio>()); int miIntPuertoServidor = 1; if (string.IsNullOrEmpty(miStrDireccionServidor)) { throw new InvalidOperationException("No se ha podido conectar con el servidor."); } return new CanalGrpc(miStrDireccionServidor, miIntPuertoServidor); }); var serviceProvider = services.BuildServiceProvider(); // 若启动时需要解析服务,也包裹在此try块内 var canalGrpc = serviceProvider.GetRequiredService<CanalGrpc>(); } catch (InvalidOperationException ex) { MessageBox.Show(ex.Message, "Error de Conexión", MessageBoxButton.OK, MessageBoxImage.Error); Shutdown(); // 关闭应用 return; } base.OnStartup(e); }
注:原GetDireccionServidor返回空字符串的场景也要处理,避免后续创建CanalGrpc实例时出现隐性错误。
二、延迟初始化服务,避免启动时阻塞
如果不需要在启动阶段就检测连接,可以将CanalGrpc注册为延迟初始化实例,仅在第一次使用时尝试创建,此时可在业务逻辑中捕获异常:
修改注册逻辑
services.AddSingleton<Lazy<CanalGrpc>>(miServiceProvider => { return new Lazy<CanalGrpc>(() => { string miStrDireccionServidor = GetDireccionServidor(miServiceProvider.GetRequiredService<IConfiguracionServicio>()); int miIntPuertoServidor = 1; if (string.IsNullOrEmpty(miStrDireccionServidor)) { throw new InvalidOperationException("No se ha podido conectar con el servidor."); } return new CanalGrpc(miStrDireccionServidor, miIntPuertoServidor); }); });
使用时捕获异常
在ViewModel或业务代码中调用时处理:
public class MainViewModel { private readonly Lazy<CanalGrpc> _canalGrpcLazy; public MainViewModel(Lazy<CanalGrpc> canalGrpcLazy) { _canalGrpcLazy = canalGrpcLazy; } public void ConectarServidor() { try { var canalGrpc = _canalGrpcLazy.Value; // 执行后续业务逻辑 } catch (InvalidOperationException ex) { MessageBox.Show(ex.Message, "Error de Conexión", MessageBoxButton.OK, MessageBoxImage.Error); } } }
三、调整地址检测逻辑,提前处理异常
修改GetDireccionServidor方法,不直接抛出异常,而是返回可空字符串,再在服务注册或启动阶段判断结果:
修改后的地址检测方法
private string? GetDireccionServidor(IConfiguracionServicio configuracion) { try { Ping miPing = new Ping(); PingOptions misOpcionesPing = new PingOptions { DontFragment = true }; var direcciones = new List<string> { "1.1.1.1", "2.2.2.2", "3.3.3.3" }; foreach (var dir in direcciones) { PingReply miRespuestoPing = miPing.Send(dir, 500); if (miRespuestoPing.Status == IPStatus.Success) { return dir; } } return null; } catch (Exception ex) { // 可在此处添加日志记录 return null; } }
注册时的结果判断
services.AddSingleton<CanalGrpc>(miServiceProvider => { var configuracion = miServiceProvider.GetRequiredService<IConfiguracionServicio>(); string? miStrDireccionServidor = GetDireccionServidor(configuracion); if (miStrDireccionServidor == null) { throw new InvalidOperationException("No se ha podido conectar con el servidor."); } int miIntPuertoServidor = 1; return new CanalGrpc(miStrDireccionServidor, miIntPuertoServidor); });
此方式可将异常统一抛到启动入口处理,也可结合延迟初始化灵活调整。
内容的提问来源于stack exchange,提问作者Álvaro García
相关产品推荐
相关产品推荐

