Question

Je travaille sur l'implémentation d'une agrégation d'événements avec Prism. J'ai quelques modules et je veux que chacun d'eux s'abonne à des événements qui leur indiquent quand ils sont sollicités. J'ai commencé par faire un exemple clair avec abonné et éditeur dans le shell. Pas de problèmes là-bas. À présent; lorsque je déplace les abonnés vers mes modules, ils ne se déclenchent pas. Ce qui est encore plus étrange, c’est que cela a effectivement fonctionné à quelques reprises - ce dont je suis en attente dans un point d’arrêt. Il me semble donc qu’il s’agit d’une condition de concurrence, mais je ne comprends pas pourquoi.

Hypothèse formulée: Je n'ai pas besoin de configurer IEventAggregator n'importe où, par exemple. vous inscrire dans le conteneur IoC? Ceci est construit dans Prism de telle sorte que je n'ai qu'une seule instance de l'agrégateur d'événements, non?

La question est donc de savoir comment / où / quand je dois configurer mes abonnés. Existe-t-il un ordre spécifique pour les articles, etc. Dans mon exemple simplifié, j'ai un module MyModule. Le programme d'amorçage ajoutera MyModule au catalogue - le rendant ainsi initialisé:

catalog.AddModule(typeof(MyModule));

MyModule stockera l'agrégateur et l'utilisera pour s'abonner à MyModuleRequestedEvent. Il utilise également un registre de menu pour s'inscrire dans le menu de l'application. L’idée est qu’en fin de compte, le fait de cliquer sur le menu déclenche l’événement en informant MyModule de sa demande. Ensuite, je veux que ce soit la responsabilité de MyModule de déterminer quoi faire.

public MyModule(IEventAggregator aggregator, IApplicationMenuRegistry menu)
{
    _applicationMenu = menu;
    _aggregator = aggregator;
}

public void Initialize()
{
    var evnt = _aggregator.GetEvent<MyModuleRequestedEvent>();
    evnt.Subscribe(MyModuleRequested);
    _applicationMenu.RegisterMenuItem("MyModule", evnt);
}

public void MyModuleRequested(bool b)
{
    MessageBox.Show("MyModule requested");
}

Maintenant, j'ai un bouton dans mon shell qui va publier cet événement. Le shell obtient le même agrégateur d'événements (?) Lorsqu'il est résolu.

public Shell(IEventAggregator aggregator)
{
    InitializeComponent();
    var evnt = aggregator.GetEvent<MyModuleRequestedEvent>();
    EventTriggerButton.Click += (s, e) => evnt.Publish(true);
}

Notes:

  • avoir vérifié que l'événement est publié. L'ajout d'un abonné dans le shell obligera également cet abonné à recevoir l'événement.
  • Encore une fois; l'abonné dans MyModule n'est pas déclenché. Cependant, étrangement, cela a été fait à quelques reprises.
  • Je n'utilise pas l'entrée de l'événement. Il semblait que vous deviez avoir un type d'entrée, alors je suis parti avec un boeuf factice. Puis-je me débarrasser de ça ..?
Était-ce utile?

La solution

L’agrégateur d’événements Prism utilise des références faibles pour établir un lien avec les événements. Ceci afin d'éviter les fuites de mémoire des gestionnaires d'événements.

Une fois que l'initialiseur de module a été exécuté, il est éliminé. Votre gestionnaire d'événements est donc détruit avant que l'événement ne soit déclenché. Vous pouvez demander à Prism de conserver le gestionnaire d’événements en utilisant une surcharge de Souscription.

evnt.Subscribe(MyModuleRequested, true);

En tant que modèle, j’ai tendance à placer tous les abonnés d’événement dans une classe distincte et à appeler cette classe à partir de la méthode modules Initialize. De cette façon, les événements restent en vie mais séparés tant que le module est toujours détruit.

Autres conseils

Donc, je viens de recevoir une théorie, mais pas le temps de la tester pour le moment. Faisons-la demain.

Question: L’ajout de modules au catalogue Module les gardera-t-il en vie? J'ai supposé que ce serait le cas. Par conséquent, MyModule doit rester en vie et sera ensuite déclenché à la publication de l'événement.

protected override IModuleCatalog GetModuleCatalog()
{
    var catalog = new ModuleCatalog();
    catalog.AddModule(typeof(MyModule));
    return catalog;
}

Cependant, si cela ne maintient pas le module en vie, il est évident qu'il aura du mal à répondre à l'événement. L'objet module décède, mais il ne se désabonne pas. Je vois donc l'abonné dans la liste EventAggregator, mais l'abonné n'est plus dans les parages. Également; J'ai mentionné que cela fonctionnait de temps en temps - ce qui serait le cas si le ramasse-miettes n'avait pas le temps de retirer la corbeille avant le déclenchement de l'événement.

Est-ce que cela sonne comme le cas? Si c'est le cas, je n'ai pas encore pensé à une solution, alors n'hésitez pas à en suggérer une dans un autre fil de réponse.

Alors; Qu'est-ce que le module catalogue de toute façon? Juste une liste conservée pour l'initialisation et ensuite jetée?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top