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

Jim*_*mmy 3 c# wpf user-controls prism exception

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

现在,用户控件可以在加载时抛出异常.我想在模块级别处理异常.我的想法是将一个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>
Run Code Online (Sandbox Code Playgroud)

代码背后

public MainView()           
{
    InitializeComponent();         
}

public MainView(MainViewViewModel viewmodel, IEventAggregator eventAggregator)
    :this()  
{
    _eventAggregator = eventAggregator;  
}
Run Code Online (Sandbox Code Playgroud)

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

Dr.*_*ABT 6

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

但是,一旦您的应用程序启动,如果您希望在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

// 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
    }
}
Run Code Online (Sandbox Code Playgroud)

派生视图模型的定义如下

// Derived viewmodel type
public class DerivedViewModel : ErrorViewModel
{
    public DerivedViewModel (IEventAggregator eventAggregator) : base(eventAggregator)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以通过捕获异常并推迟错误处理,将以下方法应用于视图,如下所示.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

好吧它不整洁,它不漂亮,但它再次起作用.更进一步,你可以创建一个基本视图类型来分解初始化,但是如果你继承了多个不同的基类型,那么这对你没有帮助.或者一个帮助类来推迟初始化,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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

最好的祝福