Просто стрельба из бедра. Возможно, самый простой способ поймать исключения при инициализации - разрешить доступ к агрегатору событий через одноэлемент и поднять событие из представления.
Как только приложение запустилось, если вы хотите обрабатывать необработанные исключения в потоке пользовательского интерфейса без сбоя приложения, вы можете попробовать 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;
}
}
Принимая это шаг вперед, если вы можете создать базу ViewModel как этот
// 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;
}
}
Просто некоторые идеи. Мне было бы интересно услышать, есть ли дефакто решение, так как я часто сталкивался с этой проблемой!
С наилучшими пожеланиями
Я могу видеть это решение будет работать, когда пользовательский элемент управления загружается в первый раз (InitializeComponent()). Тем не менее, пользовательский элемент управления может быть изменен действием пользователя после его успешной загрузки и, следовательно, приведет к исключению. Я изо всех сил пытаюсь выяснить, как эта ситуация может быть решена. Я думаю с точки зрения обработчика исключений, который позаботится об определенных исключениях из внутреннего объекта. Однако я не вижу никакой возможности сделать это в этой ситуации. – Jimmy
@Jimmy вы считали событие Application.UnhandledException? –
Andrew, Application.UnhandledException может решить проблему, но она выглядит немного неправильной для модульного подхода. Кроме того, если я воспринял событие, он поймает необработанные исключения из других модулей в приложении? – Jimmy