如何在MVVM Light ViewModel中使用try catch语句?

3
我目前有一个AppDomain.CurrentDomain.UnhandledException处理程序,当应用程序崩溃时会发送给我一个堆栈跟踪。 这在大多数情况下都很好用,但当我在MVVM light viewmodel中遇到异常时,堆栈跟踪可能相当神秘,无法告诉我它们发生的位置。是否有一种简单的方法来包装我的viewmodels并在其中加入try catch语句,然后将一些更有用的信息注入到异常中并重新抛出它呢?
以下是堆栈跟踪的示例:
在System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)处发生错误。
在System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)处发生错误。
在System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)处发生错误。
在System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)处发生错误。
在d:\GalaSoft\mydotnet\MvvmLight\Source\GalaSoft.MvvmLight\GalaSoft.MvvmLight (NET35)\Helpers\WeakAction.cs:line 269的GalaSoft.MvvmLight.Helpers.WeakAction.Execute()处发生错误。
在d:\GalaSoft\mydotnet\MvvmLight\Source\GalaSoft.MvvmLight\GalaSoft.MvvmLight (NET35)\Command\RelayCommand.cs:line 167的GalaSoft.MvvmLight.Command.RelayCommand.Execute(Object parameter)处发生错误。
在MS.Internal.Commands.CommandHelpers.CriticalExecuteCommandSource(ICommandSource commandSource, Boolean userInitiated)处发生错误。
在System.Windows.Controls.Primitives.ButtonBase.OnClick()处发生错误。
在System.Windows.Controls.Button.OnClick()处发生错误。
在System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)处发生错误。
在System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)处发生错误。
在System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)处发生错误。
在System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)处发生错误。
在System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)处发生错误。
在System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)处发生错误。
在System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)处发生错误。
在System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)处发生错误。
在System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)处发生错误。
在System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)处发生错误。
在System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)处发生错误。
在System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)处发生错误。
在System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)处发生错误。
在System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)处发生错误。
在System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)处发生错误。
在System.Windows.Input.InputManager.ProcessStagingArea()处发生错误。
在System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)处发生错误。
在System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)处发生错误。
在System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)处发生错误。
在System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)处发生错误。
在System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)处发生错误。
在MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)处发生错误。
在MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)处发生错误。
在System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)处发生错误。
在MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)处发生错误。
在System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)处发生错误。
在MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)处发生错误。
在MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)处发生错误。
在System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)处发生错误。
在System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)处发生错误。
在System.Windows.Threading.Dispatcher

这是由于我的视图模型中的一个方法引发了NotImplementedException,该方法被包装在一个RelayCommand中,以便我可以将一个按钮绑定到它上面。 我找不到任何指向该方法或视图模型名称的线索。


1
你能展示其中一个晦涩难懂的异常吗? - Daniel Hilgarth
已添加堆栈跟踪。我编辑的唯一内容是我的应用程序名称和包含整个项目路径的行。 - PlTaylor
那个异常有“InnerException”吗? - Daniel Hilgarth
那不仅仅是一个小小的奖励。 - PlTaylor
1
代码能够让我的错误信息更易于阅读,这使我感到高兴。 - PlTaylor
显示剩余2条评论
2个回答

6

你应该在InnerException属性中获得更多信息。

如果我没有错的话,你的主要异常类型是TargetInvocationException。你可以编写一个小方法来解开它:

public Exception Unwrap(TargetInvocationException root)
{
    if(root.InnerException == null)
        return root;
    var innerException = root.InnerException as TargetInvocationException;
    if(innerException == null)
        return root.InnerException;

    return Unwrap(innerException);
}

这种方法非常有用,因为通常你会遇到多层的TargetInvocationException,而真正的异常被埋藏在其中的3或4个异常之下。


0

如果你已经在处理AppDomain.CurrentDomain.UnhandledException事件,那你可以不在那个处理程序中添加你的信息吗?

public void MainWindow_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    Exception exception = (Exception)e.ExceptionObject;
    if (exception.TargetSite.Module.ToString() == "nameOfViewModelAssembly.dll")
    {
        if (exception.StackTrace.Contains(nameOfSomeViewModel))
        {
            throw new Exception("Problem in nameOfSomeViewModel", exception);
        }
        else if (exception.StackTrace.Contains(nameOfOtherViewModel))
        {
            throw new Exception("Problem in nameOfOtherViewModel", exception);
        }
    }
}

当然,如果你有很多视图模型,这可能会变得相当大,但我相信你可以找到更有效的方法来解决这个问题。


堆栈跟踪中没有指示它来自哪个视图模型。 - PlTaylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接