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

时间:2012-01-23 11:01:29

标签: c# wpf exception user-controls prism

我们的应用程序中有几个模块。我有一个项目,其中包含一组用于模块的自定义用户控件。请注意,此用户控件不会注入模块,而是用作XAML内联中的用户cotrol。

现在,用户控件可以在加载时抛出异常。我想在模块级别处理异常。我的想法是将一个eventaggregator注入模块构造函数,并在捕获异常时触发错误事件。

例如,模块的主视图如下

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;  
}

在哪里可以从模块级别的用户控件中捕获激活?

1 个答案:

答案 0 :(得分:6)

只是从臀部射击。在初始化时捕获异常的最简单方法可能是允许通过单例访问事件聚合器并从视图中引发事件。

一旦你的应用程序启动了,如果你希望在没有应用程序崩溃的情况下处理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;
    }
}

更进一步,如果你可以创建像这样的基本视图模型

// 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;
    }
}

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

祝你好运