棱镜应用程序中的异常处理策略
本文关键字:异常处理 策略 应用程序 棱镜 | 更新日期: 2023-09-27 18:21:03
我们的应用程序中有几个模块。我有一个项目,其中包含一组在模块中使用的自定义用户控件。请注意,此用户控件并没有注入到模块中,而是用作XAML内联中的用户控件。
现在,用户控件可以在加载时抛出异常。我想在模块级别处理异常。我的想法是在模块构造函数中注入一个事件聚合器,在捕捉到异常时,我可以触发一个错误事件。
例如,模块的主视图如下
XAML
<inf:DockBase
x:Class="MainView"
xmlns:inf="clr-namespace:Infrastructure"
xmlns:usercontrols="clr-namespace:UserControls;assembly=Myusercontrollib">
<Grid>
<!--some code here-->
<usercontrols:CustomListControl source={Binding myList}/>
</Grid>
</inf:DockBase>
代码隐藏
public MainView()
{
InitializeComponent();
}
public MainView(MainViewViewModel viewmodel, IEventAggregator eventAggregator)
:this()
{
_eventAggregator = eventAggregator;
}
我在哪里可以从模块级别的用户控件中捕获异常??
只是从臀部投篮。在初始化时捕获异常的最简单方法可能是允许通过singleton访问事件聚合器并从视图中引发事件。
但是,一旦应用程序启动,如果希望在UI线程上处理未处理的异常而不使应用程序崩溃,则可以尝试application.UnhandledException事件。这允许您在Silverlight或WPF中处理异常并进行处理,然后取消或继续允许异常将您逐出应用程序。
免责声明:编译和执行中的所有未经测试的代码
public class MyView : UserControl
{
public MyView()
{
// Hardly best practice, but it'll work
try
{
InitializeComponent();
}
catch(Exception caught)
{
EventAggregatorService.Instance.GetEvent<XamlExceptionEvent>().Publish(/* ... */);
}
}
}
public class EventAggregatorService
{
public IEventAggregator Instance { get { return _instance; } }
// NOTE: Must be called once in your bootstrapper to set the EA instance
public static void SetEventAggregator(IEventAggregator instance)
{
_instance = instance;
}
}
更进一步,如果你能创建一个像这样的基本视图模型
// Base viewmodel type to handle errors
public abstract class ErrorViewModel
{
private IEventAggregator eventAggregator;
protected ErrorViewModel(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
}
public void HandleInitializationException(object view, Exception caught)
{
// Publish event via _eventAggregator
}
}
派生视图模型定义如下
// Derived viewmodel type
public class DerivedViewModel : ErrorViewModel
{
public DerivedViewModel (IEventAggregator eventAggregator) : base(eventAggregator)
{
}
}
通过捕获异常并推迟错误处理,可以将以下方法应用于视图,如下所示。
public class MyView : UserControl
{
private readonly Exception _ex;
public MyView()
{
try { InitializeComponent(); } catch (Exception caught) { _ex = caught; }
}
protected override OnDataContextChanged(object sender, EventArgs e)
{
if (_ex == null) return;
var vm = view.DataContext as ErrorViewModel;
if (vm != null)
{
vm.HandleInitializationException(view, caught);
return;
}
throw new Exception("Error occurred during View initialization", _ex);
}
}
好吧,它不整洁,也不漂亮,但它还是可以的。更进一步,您可能也可以创建一个基视图类型来排除初始化,但是,如果您继承了多个不同的基类型,那么这对您没有帮助。或者,一个延迟初始化的帮助类,通过反射调用Initializecomponent()
方法。
最后,UnhandledException处理的代码:
public partial class App : Application
{
public App()
{
this.UnhandledException += this.Application_UnhandledException;
InitializeComponent();
}
private void Application_UnhandledException(object sender,
ApplicationUnhandledExceptionEventArgs e)
{
if (e.ExceptionObject is FileNotFoundException)
{
// Inform the user
EventAggregatorService.Instance.GetEvent<MyUnhandledExceptionEvent>().Publish(/* ... */);
// Recover from the error
e.Handled = true;
return;
}
}
只是一些想法。我很想知道是否有一个事实上的解决方案,因为我经常遇到这个问题!
向致以最良好的问候