棱镜应用程序中的异常处理策略

本文关键字:异常处理 策略 应用程序 棱镜 | 更新日期: 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;
    }
}

只是一些想法。我很想知道是否有一个事实上的解决方案,因为我经常遇到这个问题!

向致以最良好的问候