Domanda

Sto lavorando per implementare un'aggregazione di eventi con Prism. Ho alcuni moduli e desidero che ciascuno di essi si iscriva agli eventi che indicano quando vengono richiesti. Ho iniziato facendo un chiaro esempio sia con l'iscrizione che con l'editore nella shell. Nessun problema lì. Adesso; quando sposto gli abbonati ai miei moduli non vengono attivati. La cosa ancora più strana è che in realtà ha funzionato un paio di volte - tutto ciò che ho aspettato in un breakpoint. Quindi mi sembra una condizione di gara, ma non capisco perché.

Presupposto formulato: non è necessario configurare IEventAggregator da nessuna parte, ad es. registrarsi nel contenitore IoC? Questo è integrato in Prism in modo tale che ho solo un'istanza dell'aggregatore di eventi, giusto?

Quindi, la domanda è sostanzialmente come / dove / quando dovrei impostare i miei abbonati. Esiste un ordine specifico su cose ecc.? Nel mio esempio semplificato ho un modulo MyModule. Bootstrapper aggiungerà MyModule al catalogo rendendolo inizializzato:

catalog.AddModule(typeof(MyModule));

MyModule memorizzerà l'aggregatore e lo utilizzerà per iscriversi a MyModuleRequestedEvent. Utilizza anche un registro di menu per registrarsi nel menu dell'applicazione. L'idea è che eventualmente fare clic sul menu dovrebbe attivare l'evento, avvisando MyModule che è stato richiesto. Quindi voglio che sia responsabilità di MyModule capire cosa fare di più.

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

Ora ho un pulsante nella mia shell che pubblicherà questo evento. La shell ottiene lo stesso aggregatore di eventi (?) Quando risolto.

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

Note:

  • Ho verificato che l'evento è stato pubblicato. L'aggiunta di un abbonato anche nella shell farà sì che questo abbonato riceva l'evento.
  • Anche in questo caso; l'abbonato in MyModule non è attivato. Tuttavia, è stato - stranamente - in alcune occasioni.
  • Non utilizzo l'input per l'evento. Sembrava che avessi bisogno di un input-type, quindi sono andato con un bool fittizio. Posso liberarmi di questo ..?
È stato utile?

Soluzione

Prism Event Aggregator utilizza riferimenti deboli per collegarsi agli eventi. Questo per evitare perdite di memoria dai gestori di eventi.

Una volta eseguito l'inizializzatore di un modulo, questo viene eliminato, quindi il gestore dell'evento viene distrutto prima che l'evento venga generato. Puoi dire a Prism di mantenere il gestore dell'evento in giro usando un sovraccarico di Iscriviti.

evnt.Subscribe(MyModuleRequested, true);

Come modello, tendo a mettere tutti gli abbonati ad eventi in una classe separata e chiamare quella classe dal metodo Initialize dei moduli. In questo modo gli eventi rimangono vivi ma separati mentre il modulo è ancora distrutto.

Altri suggerimenti

Quindi, ho appena avuto una teoria, ma non c'è tempo per provarla adesso. Lo farò domani.

Domanda: l'aggiunta di moduli a ModuleCatalogue li manterrà in vita? Ho pensato che sarebbe. Quindi - MyModule dovrebbe rimanere in vita - e quindi verrà attivato quando l'evento verrà pubblicato.

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

Tuttavia, se questo non mantiene in vita il modulo, è ovvio che sarà difficile rispondere all'evento. L'oggetto modulo muore, ma non annulla l'iscrizione, quindi vedrò l'abbonato nell'elenco EventAggregator, ma l'abbonato non è più presente. Anche; Ho detto che in effetti funziona di tanto in tanto - il che sarebbe il caso se il garbage collector non avesse avuto il tempo di portare fuori la spazzatura prima che l'evento venisse attivato.

Ti sembra il caso? In tal caso, non ho ancora pensato a una soluzione, quindi puoi suggerirne una in un thread di risposta diverso.

; che cos'è comunque il ModuleCataloge? Solo un elenco conservato per l'inizializzazione e quindi eliminato?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top