MVVM Light: cómo cancelar el registro de Messenger

Me encanta el MVVM Light's Messenger y su flexibilidad, sin embargo, estoy experimentando pérdidas de memoria cuando olvido anular el registro explícitamente de los destinatarios (en Silverlight 4).

La causa se explicaaqu, pero estoy de acuerdo, ya que creo que es una buena práctica anular el registro explícitamente de los destinatarios de todos modos en lugar de confiar en el uso de referencias débiles por parte del Messenger. El problema es que es más fácil decirlo que hacerlo.

ViewModels son fáciles: generalmente tiene control total sobre su ciclo de vida y puede simplementeCleanup() ellos cuando ya no son necesarios.

Puntos de vist por otro lado son más complicados porque se crean instancias y se destruyen a través de DataTemplates. Por ej. puedes pensar en unaItemsControl conMyView como DataTemplate, vinculado a unaObservableCollection<MyViewModel>. LosMyViewos controles @ son creados / recopilados por el motor de enlace y no tiene una buena manera de llamar manualmente a Cleanup () en ellos.

Tengo una solución en mente, pero me gustaría saber si es un patrón decente o si hay mejores alternativas. La idea es enviar un mensaje específico desde el ViewModel para indicarle a las Vistas asociadas que dispongan:

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

Así que cuando llamas a Cleanup () en una vistaModelo, todas las vistas que lo usan como DataContext también ejecutarán su Cleanup () local.

¿Qué piensas? ¿Me estoy perdiendo algo obvio?

Respuestas a la pregunta(3)

Su respuesta a la pregunta