Pergunta

Estou trabalhando na implementação de uma agregação de eventos com Prism. Eu tenho alguns módulos e quero que cada um deles se inscreva em eventos que lhes dizem quando são solicitados. Comecei a fazer um exemplo totalmente simples, com a subscrita e o editor no shell. Sem problemas lá. Agora; Quando movo os assinantes para meus módulos, eles não são acionados. O que é ainda mais estranho é que ele realmente funcionou algumas vezes - o que estou pendente em um ponto de interrupção. Então, parece -me ser alguma condição de corrida, mas não entendo o porquê.

Suposição feita: Não preciso configurar o IEventAggregator em nenhum lugar - por exemplo, registrando -se no contêiner do COI? Isso é incorporado ao prisma, de modo que eu tenho apenas uma instância do agregador de eventos, certo?

Portanto, a pergunta é basicamente como/onde/quando eu deveria configurar meus assinantes. Existe uma ordem específica sobre coisas etc? No meu exemplo simplificado, tenho um módulo MyModule. O bootstrapper adicionará mymodule ao catálogo - fazendo com que ele seja inicializado:

catalog.AddModule(typeof(MyModule));

O MyModule armazenará o agregador e usará isso para assinar o MyModulerequestedEvent. Ele também usa um registro de menu para se registrar no menu do aplicativo. A idéia é que, eventualmente, clicar no menu deve acionar o evento - notificando o MyModule que ele foi solicitado. Então eu quero que seja a responsabilidade do MyModule descobrir o que fazer mais.

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

Agora, tenho um botão no meu shell que publicará este evento. O shell obtém o mesmo (?) Agregador do evento quando resolvido.

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

Notas:

  • Verificaram que o evento foi publicado. Adicionar um assinante no shell também fará com que este assinante receba o evento.
  • Novamente; O assinante no MyModule não é acionado. No entanto, foi - estranhamente - em algumas ocasiões.
  • Não uso a entrada para o evento. Parecia que você precisava ter algum tipo de entrada, então eu apenas fui com um bool fictício. Posso me livrar disso ..?
Foi útil?

Solução

O agregador de eventos do Prism usa referências fracas para link para os eventos. Isso é para impedir que os vazamentos de memória manipuladores de eventos.

Depois que um inicializador de módulo é executado, ele é descartado, o seu manipulador de eventos está sendo destruído antes que o evento seja demitido. Você pode dizer ao Prism para manter o manipulador de eventos usando uma sobrecarga de inscrição.

evnt.Subscribe(MyModuleRequested, true);

Como padrão, costumo colocar qualquer assinante de evento em uma classe separada e chamo essa classe do método inicialize dos módulos. Dessa forma, os eventos permanecem vivos, mas separados enquanto o módulo ainda está destruído.

Outras dicas

Então, acabei de ter uma teoria, mas não há tempo para testá -la agora .. farei amanhã.

Pergunta: A adição de módulos ao ModuleCatalogue os manterá vivos? Eu assumi que sim. Portanto - o mymodule deve permanecer vivo - e depois será acionado quando o evento for publicado.

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

No entanto, se isso não mantiver o módulo vivo, é óbvio que terá dificuldade em responder ao evento. O objeto do módulo morre, mas não cancela a inscrição - portanto, verei o assinante na lista EventAggregator, mas o assinante não está mais por perto. Também; Mencionei que, de fato, funciona de fato ocasionalmente - o que seria o caso se o coletor de lixo não tivesse tempo de tirar o lixo antes que o evento seja acionado.

Isso soa como o caso? Em caso afirmativo - ainda não pensei em uma solução, então você pode sugerir um em um tiro de resposta diferente ..

Então; Qual é o ModuleCataloge, afinal? Apenas uma lista mantida para inicialização e depois jogada fora?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top