MVVM Light: comment désenregistrer Messenger

J’adore le Messenger de MVVM Light et sa flexibilité, mais je rencontre des memory leaks lorsque j’oublie de désenregistrer explicitement les destinataires (dans Silverlight 4).

La cause est expliquée ici , mais je suis d’accord avec cela car je pense que c’est une bonne pratique de désinscrire explicitement les destinataires de toute façon plutôt que de compter sur l’utilisation de références faibles par le Messager. Le problème est que c’est plus facile à dire qu’à faire.

J’ai une solution en tête mais je voudrais savoir si c’est un modèle décent ou s’il existe de meilleures alternatives. L’idée est d’envoyer un message spécifique à partir de ViewModel pour indiquer aux vues associées de disposer:

 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(this, m => { if (m.SenderViewModel == this.DataContext) this.Cleanup(); }); } public void Cleanup() { Messenger.Default.Unregister(this); Messenger.Default.Unregister(this); } } 

Ainsi, lorsque vous appelez Cleanup () sur un viewModel, toutes les vues qui l’utilisent comme DataContext exeute également leur Cleanup () local.

Qu’est-ce que tu penses? Est-ce que je manque quelque chose d’évident?

La classe ViewModelLocator permet de conserver un magasin centralisé pour vos modèles de vue. Vous pouvez utiliser cette classe pour gérer de nouvelles versions et nettoyer les anciennes. Je référence toujours mon modèle de vue de la vue via le localisateur, donc j’ai toujours du code que je peux exécuter pour gérer ces choses. Vous pourriez essayer ça.

De plus, j’utilise la méthode Cleanup pour appeler Messenger.Unregister(this) , qui nettoie toutes les références du messager pour cet object. Vous devez appeler .Cleanup () à chaque fois, mais telle est la vie 🙂

Je n’ai pas utilisé MVVM Light (bien que j’aie entendu de bonnes choses), mais si vous voulez une implémentation de Messenger qui utilise WeakReferences, jetez un œil sur le Messenger inclus ici http://mvvmfoundation.codeplex.com/ .

MVVM Light Messenger utilise WeakAction (WeakReference). Vous n’avez donc pas besoin de vous désinscrire explicitement.