我们的应用程序中有几个模块。我有一个项目,其中包含一组在模块中使用的自定义用户控件。请注意,此用户控件不会注入(inject)模块,而是用作 XAML 内联中的用户控件。
现在用户控件可以在加载时抛出异常。我想在模块级别处理异常。我的想法是我将一个事件聚合器注入(inject)到模块构造函数中,并且在捕获到异常时我可以触发一个错误事件。
例如模块的主视图如下
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;
}
我在哪里可以从模块级别的用户控件中捕获异常??
最佳答案
只是从臀部射击。也许在初始化时捕获异常的最简单方法是允许通过单例访问事件聚合器并从 View 中引发事件。
但是,一旦您的应用程序启动后,如果您希望在不让应用程序崩溃的情况下处理 UI 线程上未处理的异常,您可以尝试 Application.UnhandledException event .这使您可以处理 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;
}
}
更进一步,如果您可以像这样创建一个基本 View 模型
// 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
}
}
派生 View 模型是这样定义的
// Derived viewmodel type
public class DerivedViewModel : ErrorViewModel
{
public DerivedViewModel (IEventAggregator eventAggregator) : base(eventAggregator)
{
}
}
您可以通过捕获异常和延迟错误处理来将以下方法应用于您的 View ,如下所示。
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);
}
}
好吧,它不整洁也不漂亮,但它还是可以工作的。更进一步,您也许可以创建一个基本 View 类型来分解初始化,但是如果您继承多个不同的基本类型,那么这对您没有帮助。或者,延迟初始化的帮助类,通过反射调用 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;
}
}
只是一些想法。我很想知道是否有实际的解决方案,因为我经常遇到这个问题!
最好的问候
关于c# - Prism 应用中的异常处理策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8970572/