Мне нравится MVVM Light Messenger и его гибкость, однако я испытываю утечку памяти, когда забываю явно отменить регистрацию получателей (в Silverlight 4).
Причина объясняется здесь, но я в порядке, поскольку я считаю хорошей практикой явно отменить регистрацию получателей, а не полагаться на использование Messenger слабых ссылок. Проблема в том, что проще сказать, чем сделать.
-
ViewModels просты: вы обычно имеете полный контроль над своим жизненным циклом и можете просто
Cleanup()
их, когда они больше не нужны. -
Представления, с другой стороны, сложнее, поскольку они создаются и уничтожаются с помощью DataTemplates. Напр. вы можете думать о
ItemsControl
сMyView
как DataTemplate, привязанным кObservableCollection<MyViewModel>
. Элементы управленияMyView
создаются/собираются механизмом привязки, и у вас нет хорошего способа ручного вызова Cleanup() на них.
У меня есть решение, но хотелось бы знать, есть ли у него приличный образец или есть лучшие альтернативы. Идея состоит в том, чтобы отправить конкретное сообщение из ViewModel, чтобы сообщить связанным View (s):
public class MyViewModel : ViewModelBase
{
...
public override void Cleanup()
{
// unregisters its own messages, so that we risk no leak
Messenger.Default.Unregister<...>(this);
// sends a message telling that this ViewModel is being cleaned
Messenger.Default.Send(new ViewModelDisposingMessage(this));
base.Cleanup();
}
}
public class MyView : UserControl, ICleanup
{
public MyView()
{
// registers to messages it actually needs
Messenger.Default.Register<...>(this, DoSomething);
// registers to the ViewModelDisposing message
Messenger.Default.Register<ViewModelDisposingMessage>(this, m =>
{
if (m.SenderViewModel == this.DataContext)
this.Cleanup();
});
}
public void Cleanup()
{
Messenger.Default.Unregister<...>(this);
Messenger.Default.Unregister<ViewModelDisposingMessage>(this);
}
}
Поэтому, когда вы вызываете Cleanup() на viewModel, все представления, которые используют его в качестве DataContext, будут также выполнять их локальную очистку().
Как вы думаете? Мне что-то не хватает?